1 // Copyright (c) 2011 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 CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_ 6 #define CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_ 7 8 #include "base/compiler_specific.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "content/public/browser/native_web_keyboard_event.h" 11 #include "ui/gfx/animation/animation_delegate.h" 12 #include "ui/gfx/native_widget_types.h" 13 #include "ui/gfx/rect.h" 14 #include "ui/views/controls/textfield/textfield.h" 15 #include "ui/views/focus/focus_manager.h" 16 17 class BrowserView; 18 class DropdownBarHostDelegate; 19 class DropdownBarView; 20 21 namespace content { 22 class WebContents; 23 } 24 25 namespace gfx { 26 class SlideAnimation; 27 } // namespace gfx 28 29 namespace views { 30 class ExternalFocusTracker; 31 class View; 32 class Widget; 33 } // namespace views 34 35 //////////////////////////////////////////////////////////////////////////////// 36 // 37 // The DropdownBarHost implements the container widget for the UI that 38 // is shown at the top of browser contents. It uses the appropriate 39 // implementation from dropdown_bar_host_win.cc or dropdown_bar_host_aura.cc to 40 // draw its content and is responsible for showing, hiding, animating, closing, 41 // and moving the bar if needed, for example if the widget is 42 // obscuring the selection results in FindBar. 43 // 44 //////////////////////////////////////////////////////////////////////////////// 45 class DropdownBarHost : public ui::AcceleratorTarget, 46 public views::FocusChangeListener, 47 public gfx::AnimationDelegate { 48 public: 49 explicit DropdownBarHost(BrowserView* browser_view); 50 virtual ~DropdownBarHost(); 51 52 // Initializes the DropdownBarHost. This creates the widget that |view| paints 53 // into. 54 // |host_view| is the view whose position in the |browser_view_| view 55 // hierarchy determines the z-order of the widget relative to views with 56 // layers and views with associated NativeViews. 57 void Init(views::View* host_view, 58 views::View* view, 59 DropdownBarHostDelegate* delegate); 60 61 // Whether we are animating the position of the dropdown widget. 62 bool IsAnimating() const; 63 // Returns true if the dropdown bar view is visible, or false otherwise. 64 bool IsVisible() const; 65 // Selects text in the entry field and set focus. 66 void SetFocusAndSelection(); 67 // Stops the animation. 68 void StopAnimation(); 69 70 // Shows the dropdown bar. 71 virtual void Show(bool animate); 72 // Hides the dropdown bar. 73 virtual void Hide(bool animate); 74 75 // Returns the rectangle representing where to position the dropdown widget. 76 virtual gfx::Rect GetDialogPosition(gfx::Rect avoid_overlapping_rect) = 0; 77 78 // Moves the widget to the provided location, moves it to top 79 // in the z-order (HWND_TOP, not HWND_TOPMOST for windows) and shows 80 // the widget (if hidden). 81 virtual void SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) = 0; 82 83 // Overridden from views::FocusChangeListener: 84 virtual void OnWillChangeFocus(views::View* focused_before, 85 views::View* focused_now) OVERRIDE; 86 virtual void OnDidChangeFocus(views::View* focused_before, 87 views::View* focused_now) OVERRIDE; 88 89 // Overridden from ui::AcceleratorTarget: 90 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) = 0; 91 virtual bool CanHandleAccelerators() const = 0; 92 93 // gfx::AnimationDelegate implementation: 94 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 95 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 96 97 // During testing we can disable animations by setting this flag to true, 98 // so that opening and closing the dropdown bar is shown instantly, instead of 99 // having to poll it while it animates to open/closed status. 100 static bool disable_animations_during_testing_; 101 102 // Returns the browser view that the dropdown belongs to. 103 BrowserView* browser_view() const { return browser_view_; } 104 105 // Registers this class as the handler for when Escape is pressed. Once we 106 // loose focus we will unregister Escape and (any accelerators the derived 107 // classes registers by using overrides of RegisterAccelerators). See also: 108 // SetFocusChangeListener(). 109 virtual void RegisterAccelerators(); 110 111 // When we loose focus, we unregister all accelerator handlers. See also: 112 // SetFocusChangeListener(). 113 virtual void UnregisterAccelerators(); 114 115 protected: 116 // Called when the drop down bar visibility, aka the value of IsVisible(), 117 // changes. 118 virtual void OnVisibilityChanged(); 119 120 // Returns the dropdown bar view. 121 views::View* view() const { return view_; } 122 123 // Returns the focus tracker. 124 views::ExternalFocusTracker* focus_tracker() const { 125 return focus_tracker_.get(); 126 } 127 128 // Resets the focus tracker. 129 void ResetFocusTracker(); 130 131 // The focus manager we register with to keep track of focus changes. 132 views::FocusManager* focus_manager() const { return focus_manager_; } 133 134 // Returns the host widget. 135 views::Widget* host() const { return host_.get(); } 136 137 // Returns the animation offset. 138 int animation_offset() const { return animation_offset_; } 139 140 // Retrieves the boundary that the dropdown widget has to work with 141 // within the Chrome frame window. The boundary differs depending on 142 // the dropdown bar implementation. The default implementation 143 // returns the boundary of browser_view and the drop down 144 // can be shown in any client area. 145 virtual void GetWidgetBounds(gfx::Rect* bounds); 146 147 // The find bar widget needs rounded edges, so we create a polygon 148 // that corresponds to the background images for this window (and 149 // make the polygon only contain the pixels that we want to 150 // draw). The polygon is then given to SetWindowRgn which changes 151 // the window from being a rectangle in shape, to being a rect with 152 // curved edges. We also check to see if the region should be 153 // truncated to prevent from drawing onto Chrome's window border. 154 void UpdateWindowEdges(const gfx::Rect& new_pos); 155 156 // Allows implementation to tweak widget position. 157 void SetWidgetPositionNative(const gfx::Rect& new_pos, bool no_redraw); 158 159 // Returns a keyboard event suitable for forwarding. 160 content::NativeWebKeyboardEvent GetKeyboardEvent( 161 const content::WebContents* contents, 162 const ui::KeyEvent& key_event); 163 164 // Returns the animation for the dropdown. 165 gfx::SlideAnimation* animation() { 166 return animation_.get(); 167 } 168 169 private: 170 // Set the view whose position in the |browser_view_| view hierarchy 171 // determines the z-order of |host_| relative to views with layers and 172 // views with associated NativeViews. 173 void SetHostViewNative(views::View* host_view); 174 175 // The BrowserView that created us. 176 BrowserView* browser_view_; 177 178 // Our view, which is responsible for drawing the UI. 179 views::View* view_; 180 DropdownBarHostDelegate* delegate_; 181 182 // The y position pixel offset of the widget while animating the 183 // dropdown widget. 184 int animation_offset_; 185 186 // The animation class to use when opening the Dropdown widget. 187 scoped_ptr<gfx::SlideAnimation> animation_; 188 189 // The focus manager we register with to keep track of focus changes. 190 views::FocusManager* focus_manager_; 191 192 // True if the accelerator target for Esc key is registered. 193 bool esc_accel_target_registered_; 194 195 // Tracks and stores the last focused view which is not the DropdownBarView 196 // or any of its children. Used to restore focus once the DropdownBarView is 197 // closed. 198 scoped_ptr<views::ExternalFocusTracker> focus_tracker_; 199 200 // Host is the Widget implementation that is created and maintained by the 201 // dropdown bar. It contains the DropdownBarView. 202 scoped_ptr<views::Widget> host_; 203 204 // A flag to manually manage visibility. GTK/X11 is asynchronous and 205 // the state of the widget can be out of sync. 206 bool is_visible_; 207 208 DISALLOW_COPY_AND_ASSIGN(DropdownBarHost); 209 }; 210 211 #endif // CHROME_BROWSER_UI_VIEWS_DROPDOWN_BAR_HOST_H_ 212