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 UI_VIEWS_WIDGET_WIDGET_DELEGATE_H_ 6 #define UI_VIEWS_WIDGET_WIDGET_DELEGATE_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/macros.h" 13 #include "ui/accessibility/ax_enums.mojom.h" 14 #include "ui/base/ui_base_types.h" 15 #include "ui/views/view.h" 16 #include "ui/views/widget/widget.h" 17 18 namespace gfx { 19 class ImageSkia; 20 class Rect; 21 } // namespace gfx 22 23 namespace views { 24 class BubbleDialogDelegate; 25 class ClientView; 26 class DialogDelegate; 27 class NonClientFrameView; 28 class View; 29 30 // Handles events on Widgets in context-specific ways. 31 class VIEWS_EXPORT WidgetDelegate { 32 public: 33 using ClientViewFactory = 34 base::OnceCallback<std::unique_ptr<ClientView>(Widget*)>; 35 using OverlayViewFactory = base::OnceCallback<std::unique_ptr<View>()>; 36 37 // NonClientFrameViewFactory is a RepeatingCallback because the 38 // NonClientFrameView is rebuilt on Aura platforms when WindowTreeHost 39 // properties that might affect its appearance change. Rebuilding the entire 40 // NonClientFrameView is a pretty big hammer for that but it's the one we 41 // have. 42 using NonClientFrameViewFactory = 43 base::RepeatingCallback<std::unique_ptr<NonClientFrameView>(Widget*)>; 44 45 struct Params { 46 Params(); 47 ~Params(); 48 49 // The window's role. Useful values include kWindow (a plain window), 50 // kDialog (a dialog), and kAlertDialog (a high-priority dialog whose body 51 // is read when it appears). Using a role outside this set is not likely to 52 // work across platforms. 53 ax::mojom::Role accessible_role = ax::mojom::Role::kWindow; 54 55 // The accessible title for the window, often more descriptive than the 56 // plain title. If no accessible title is present the result of 57 // GetWindowTitle() will be used. 58 base::string16 accessible_title; 59 60 // Whether the window should display controls for the user to minimize, 61 // maximize, or resize it. 62 bool can_maximize = false; 63 bool can_minimize = false; 64 bool can_resize = false; 65 66 #if defined(USE_AURA) 67 // Whether to center the widget's title within the frame. 68 bool center_title = false; 69 #endif 70 71 // Controls focus traversal past the first/last focusable view. 72 // If true, focus moves out of this Widget and to this Widget's toplevel 73 // Widget; if false, focus cycles within this Widget. 74 bool focus_traverses_out = false; 75 76 // Controls whether the user can traverse a Widget's views using up/down 77 // and left/right arrow keys in addition to TAB. Applies only to the 78 // current widget so can be set independently even on widgets that share a 79 // focus manager. 80 bool enable_arrow_key_traversal = false; 81 82 // The widget's icon, if any. 83 gfx::ImageSkia icon; 84 85 // The widget's initially focused view, if any. This can only be set before 86 // this WidgetDelegate is used to initialize a Widget. 87 base::Optional<View*> initially_focused_view; 88 89 // The widget's internal name, used to identify it in window-state 90 // restoration (if this widget participates in that) and in debugging 91 // contexts. Never displayed to the user, and not translated. 92 std::string internal_name; 93 94 // The widget's modality type. Note that MODAL_TYPE_SYSTEM does not work at 95 // all on Mac. 96 ui::ModalType modal_type = ui::MODAL_TYPE_NONE; 97 98 // Whether this WidgetDelegate should delete itself when the Widget for 99 // which it is the delegate is about to be destroyed. 100 // See https://crbug.com/1119898 for more details. 101 bool owned_by_widget = false; 102 103 // Whether to show a close button in the widget frame. 104 bool show_close_button = true; 105 106 // Whether to show the widget's icon. 107 // TODO(ellyjones): What if this was implied by !icon.isNull()? 108 bool show_icon = false; 109 110 // Whether to display the widget's title in the frame. 111 bool show_title = true; 112 113 // The widget's title, if any. 114 // TODO(ellyjones): Should it be illegal to have show_title && !title? 115 base::string16 title; 116 }; 117 118 WidgetDelegate(); 119 virtual ~WidgetDelegate(); 120 121 // Sets the return value of CanActivate(). Default is true. 122 void SetCanActivate(bool can_activate); 123 124 // Called whenever the widget's position changes. 125 virtual void OnWidgetMove(); 126 127 // Called with the display changes (color depth or resolution). 128 virtual void OnDisplayChanged(); 129 130 // Called when the work area (the desktop area minus task bars, 131 // menu bars, etc.) changes in size. 132 virtual void OnWorkAreaChanged(); 133 134 // Called when the widget's initialization is beginning, right after the 135 // ViewsDelegate decides to use this WidgetDelegate for a Widget. OnWidgetInitializing()136 virtual void OnWidgetInitializing() {} 137 138 // Called when the widget's initialization is complete. OnWidgetInitialized()139 virtual void OnWidgetInitialized() {} 140 141 // Called when the window has been requested to close, after all other checks 142 // have run. Returns whether the window should be allowed to close (default is 143 // true). 144 // 145 // Can be used as an alternative to specifying a custom ClientView with 146 // the CanClose() method, or in widget types which do not support a 147 // ClientView. 148 virtual bool OnCloseRequested(Widget::ClosedReason close_reason); 149 150 // Returns the view that should have the focus when the widget is shown. If 151 // nullptr no view is focused. 152 virtual View* GetInitiallyFocusedView(); 153 bool HasConfiguredInitiallyFocusedView() const; 154 155 virtual BubbleDialogDelegate* AsBubbleDialogDelegate(); 156 virtual DialogDelegate* AsDialogDelegate(); 157 158 // Returns true if the window can be resized. 159 virtual bool CanResize() const; 160 161 // Returns true if the window can be maximized. 162 virtual bool CanMaximize() const; 163 164 // Returns true if the window can be minimized. 165 virtual bool CanMinimize() const; 166 167 // Returns true if the window can be activated. 168 virtual bool CanActivate() const; 169 170 // Returns the modal type that applies to the widget. Default is 171 // ui::MODAL_TYPE_NONE (not modal). 172 virtual ui::ModalType GetModalType() const; 173 174 virtual ax::mojom::Role GetAccessibleWindowRole(); 175 176 // Returns the title to be read with screen readers. 177 virtual base::string16 GetAccessibleWindowTitle() const; 178 179 // Returns the text to be displayed in the window title. 180 virtual base::string16 GetWindowTitle() const; 181 182 // Returns true if the window should show a title in the title bar. 183 virtual bool ShouldShowWindowTitle() const; 184 185 // Returns true if the window should show a close button in the title bar. 186 virtual bool ShouldShowCloseButton() const; 187 188 // Returns the app icon for the window. On Windows, this is the ICON_BIG used 189 // in Alt-Tab list and Win7's taskbar. 190 virtual gfx::ImageSkia GetWindowAppIcon(); 191 192 // Returns the icon to be displayed in the window. 193 virtual gfx::ImageSkia GetWindowIcon(); 194 195 // Returns true if a window icon should be shown. 196 bool ShouldShowWindowIcon() const; 197 198 // Execute a command in the window's controller. Returns true if the command 199 // was handled, false if it was not. 200 virtual bool ExecuteWindowsCommand(int command_id); 201 202 // Returns the window's name identifier. Used to identify this window for 203 // state restoration. 204 virtual std::string GetWindowName() const; 205 206 // Saves the window's bounds and "show" state. By default this uses the 207 // process' local state keyed by window name (See GetWindowName above). This 208 // behavior can be overridden to provide additional functionality. 209 virtual void SaveWindowPlacement(const gfx::Rect& bounds, 210 ui::WindowShowState show_state); 211 212 // Retrieves the window's bounds and "show" states. 213 // This behavior can be overridden to provide additional functionality. 214 virtual bool GetSavedWindowPlacement(const Widget* widget, 215 gfx::Rect* bounds, 216 ui::WindowShowState* show_state) const; 217 218 // Hooks for the end of the Widget/Window lifecycle. As of this writing, these 219 // callbacks happen like so: 220 // 1. Client code calls Widget::CloseWithReason() 221 // 2. WidgetDelegate::WindowWillClose() is called 222 // 3. NativeWidget teardown (maybe async) starts OR the operating system 223 // abruptly closes the backing native window 224 // 4. WidgetDelegate::WindowClosing() is called 225 // 5. NativeWidget teardown completes, Widget teardown starts 226 // 6. WidgetDelegate::DeleteDelegate() is called 227 // 7. Widget teardown finishes, Widget is deleted 228 // At step 3, the "maybe async" is controlled by whether the close is done via 229 // Close() or CloseNow(). 230 // Important note: for OS-initiated window closes, steps 1 and 2 don't happen 231 // - i.e, WindowWillClose() is never invoked. 232 // 233 // The default implementations of both of these call the callbacks described 234 // below. It is better to use those callback mechanisms than to override one 235 // of these methods. 236 virtual void WindowClosing(); 237 238 // It should not be necessary to override this method in new code; instead, 239 // consider using either SetOwnedByWidget() if you need that ownership 240 // behavior, or RegisterDeleteDelegateCallback() if you need to attach 241 // behavior before deletion but want the default deletion behavior. 242 virtual void DeleteDelegate(); 243 244 // Called when the user begins/ends to change the bounds of the window. OnWindowBeginUserBoundsChange()245 virtual void OnWindowBeginUserBoundsChange() {} OnWindowEndUserBoundsChange()246 virtual void OnWindowEndUserBoundsChange() {} 247 248 // Returns the Widget associated with this delegate. 249 virtual Widget* GetWidget(); 250 virtual const Widget* GetWidget() const; 251 252 // Get the view that is contained within this widget. 253 // 254 // WARNING: This method has unusual ownership behavior: 255 // * If the returned view is owned_by_client(), then the returned pointer is 256 // never an owning pointer; 257 // * If the returned view is !owned_by_client() (the default & the 258 // recommendation), then the returned pointer is *sometimes* an owning 259 // pointer and sometimes not. Specifically, it is an owning pointer exactly 260 // once, when this method is being used to construct the ClientView, which 261 // takes ownership of the ContentsView() when !owned_by_client(). 262 // 263 // Apart from being difficult to reason about this introduces a problem: a 264 // WidgetDelegate can't know whether it owns its contents view or not, so 265 // constructing a WidgetDelegate which one does not then use to construct a 266 // Widget (often done in tests) leaks memory in a way that can't be locally 267 // fixed. 268 // 269 // TODO(ellyjones): This is not tenable - figure out how this should work and 270 // replace it. 271 virtual View* GetContentsView(); 272 273 // Returns ownership of the contents view, which means something similar to 274 // but not the same as C++ ownership in the unique_ptr sense. The caller 275 // takes on responsibility for either destroying the returned View (if it 276 // is !owned_by_client()) or not (if it is owned_by_client()). Since this 277 // returns a raw pointer, this method serves only as a declaration of intent 278 // by the caller. 279 // 280 // It is only legal to call this method one time on a given WidgetDelegate 281 // instance. 282 // 283 // In future, this method will begin returning a unique_ptr<View> instead, 284 // and will eventually be renamed to TakeContentsView() once WidgetDelegate 285 // no longer retains any reference to the contents view internally. 286 View* TransferOwnershipOfContentsView(); 287 288 // Called by the Widget to create the Client View used to host the contents 289 // of the widget. 290 virtual ClientView* CreateClientView(Widget* widget); 291 292 // Called by the Widget to create the NonClient Frame View for this widget. 293 // Return NULL to use the default one. 294 virtual std::unique_ptr<NonClientFrameView> CreateNonClientFrameView( 295 Widget* widget); 296 297 // Called by the Widget to create the overlay View for this widget. Return 298 // NULL for no overlay. The overlay View will fill the Widget and sit on top 299 // of the ClientView and NonClientFrameView (both visually and wrt click 300 // targeting). 301 virtual View* CreateOverlayView(); 302 303 // Returns true if window has a hit-test mask. 304 virtual bool WidgetHasHitTestMask() const; 305 306 // Provides the hit-test mask if HasHitTestMask above returns true. 307 virtual void GetWidgetHitTestMask(SkPath* mask) const; 308 309 // Returns true if event handling should descend into |child|. 310 // |location| is in terms of the Window. 311 virtual bool ShouldDescendIntoChildForEventHandling( 312 gfx::NativeView child, 313 const gfx::Point& location); 314 315 // Populates |panes| with accessible panes in this window that can 316 // be cycled through with keyboard focus. GetAccessiblePanes(std::vector<View * > * panes)317 virtual void GetAccessiblePanes(std::vector<View*>* panes) {} 318 319 // Setters for data parameters of the WidgetDelegate. If you use these 320 // setters, there is no need to override the corresponding virtual getters. 321 void SetAccessibleRole(ax::mojom::Role role); 322 void SetAccessibleTitle(base::string16 title); 323 void SetCanMaximize(bool can_maximize); 324 void SetCanMinimize(bool can_minimize); 325 void SetCanResize(bool can_resize); 326 void SetFocusTraversesOut(bool focus_traverses_out); 327 void SetEnableArrowKeyTraversal(bool enable_arrow_key_traversal); 328 void SetIcon(const gfx::ImageSkia& icon); 329 void SetInitiallyFocusedView(View* initially_focused_view); 330 void SetModalType(ui::ModalType modal_type); 331 void SetOwnedByWidget(bool delete_self); 332 void SetShowCloseButton(bool show_close_button); 333 void SetShowIcon(bool show_icon); 334 void SetShowTitle(bool show_title); 335 void SetTitle(const base::string16& title); 336 void SetTitle(int title_message_id); 337 #if defined(USE_AURA) 338 void SetCenterTitle(bool center_title); 339 #endif 340 341 template <typename T> SetContentsView(std::unique_ptr<T> contents)342 T* SetContentsView(std::unique_ptr<T> contents) { 343 DCHECK(!contents->owned_by_client()); 344 T* raw_contents = contents.get(); 345 SetContentsViewImpl(contents.release()); 346 return raw_contents; 347 } 348 349 template <typename T> SetContentsView(T * contents)350 T* SetContentsView(T* contents) { 351 DCHECK(contents->owned_by_client()); 352 SetContentsViewImpl(contents); 353 return contents; 354 } 355 356 // A convenience wrapper that does all three of SetCanMaximize, 357 // SetCanMinimize, and SetCanResize. 358 void SetHasWindowSizeControls(bool has_controls); 359 360 void RegisterWidgetInitializingCallback(base::OnceClosure callback); 361 void RegisterWidgetInitializedCallback(base::OnceClosure callback); 362 void RegisterWindowWillCloseCallback(base::OnceClosure callback); 363 void RegisterWindowClosingCallback(base::OnceClosure callback); 364 void RegisterDeleteDelegateCallback(base::OnceClosure callback); 365 366 void SetClientViewFactory(ClientViewFactory factory); 367 void SetNonClientFrameViewFactory(NonClientFrameViewFactory factory); 368 void SetOverlayViewFactory(OverlayViewFactory factory); 369 370 // Called to notify the WidgetDelegate of changes to the state of its Widget. 371 // It is not usually necessary to call these from client code. 372 void WidgetInitializing(Widget* widget); 373 void WidgetInitialized(); 374 void WidgetDestroying(); 375 void WindowWillClose(); 376 377 // Returns true if the title text should be centered. 378 bool ShouldCenterWindowTitleText() const; 379 focus_traverses_out()380 bool focus_traverses_out() const { return params_.focus_traverses_out; } enable_arrow_key_traversal()381 bool enable_arrow_key_traversal() const { 382 return params_.enable_arrow_key_traversal; 383 } owned_by_widget()384 bool owned_by_widget() const { return params_.owned_by_widget; } 385 set_internal_name(std::string name)386 void set_internal_name(std::string name) { params_.internal_name = name; } internal_name()387 std::string internal_name() const { return params_.internal_name; } 388 389 private: 390 // We're using a vector of OnceClosures instead of a OnceCallbackList because 391 // most of the clients of WidgetDelegate don't have a convenient place to 392 // store the CallbackLists' subscription objects. 393 using ClosureVector = std::vector<base::OnceClosure>; 394 395 friend class Widget; 396 397 void SetContentsViewImpl(View* contents); 398 399 // The Widget that was initialized with this instance as its WidgetDelegate, 400 // if any. 401 Widget* widget_ = nullptr; 402 Params params_; 403 404 View* default_contents_view_ = nullptr; 405 bool contents_view_taken_ = false; 406 bool can_activate_ = true; 407 408 View* unowned_contents_view_ = nullptr; 409 std::unique_ptr<View> owned_contents_view_; 410 411 // Managed by Widget. Ensures |this| outlives its Widget. 412 bool can_delete_this_ = true; 413 414 // The first two are stored as unique_ptrs to make it easier to check in the 415 // registration methods whether a callback is being registered too late in the 416 // WidgetDelegate's lifecycle. 417 std::unique_ptr<ClosureVector> widget_initializing_callbacks_; 418 std::unique_ptr<ClosureVector> widget_initialized_callbacks_; 419 ClosureVector window_will_close_callbacks_; 420 ClosureVector window_closing_callbacks_; 421 ClosureVector delete_delegate_callbacks_; 422 423 ClientViewFactory client_view_factory_; 424 NonClientFrameViewFactory non_client_frame_view_factory_; 425 OverlayViewFactory overlay_view_factory_; 426 427 DISALLOW_COPY_AND_ASSIGN(WidgetDelegate); 428 }; 429 430 // A WidgetDelegate implementation that is-a View. Used to override GetWidget() 431 // to call View's GetWidget() for the common case where a WidgetDelegate 432 // implementation is-a View. Note that WidgetDelegateView is not owned by 433 // view's hierarchy and is expected to be deleted on DeleteDelegate call. 434 class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View { 435 public: 436 METADATA_HEADER(WidgetDelegateView); 437 438 WidgetDelegateView(); 439 ~WidgetDelegateView() override; 440 441 // WidgetDelegate: 442 Widget* GetWidget() override; 443 const Widget* GetWidget() const override; 444 View* GetContentsView() override; 445 446 private: 447 DISALLOW_COPY_AND_ASSIGN(WidgetDelegateView); 448 }; 449 450 } // namespace views 451 452 #endif // UI_VIEWS_WIDGET_WIDGET_DELEGATE_H_ 453