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