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