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 #include "ui/views/widget/widget_delegate.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/check.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/accessibility/ax_enums.mojom.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/display/display.h"
15 #include "ui/display/screen.h"
16 #include "ui/gfx/image/image_skia.h"
17 #include "ui/views/metadata/metadata_impl_macros.h"
18 #include "ui/views/view.h"
19 #include "ui/views/views_delegate.h"
20 #include "ui/views/widget/widget.h"
21 #include "ui/views/window/client_view.h"
22
23 namespace views {
24
25 namespace {
26
CreateDefaultClientView(WidgetDelegate * delegate,Widget * widget)27 std::unique_ptr<ClientView> CreateDefaultClientView(WidgetDelegate* delegate,
28 Widget* widget) {
29 return std::make_unique<ClientView>(
30 widget, delegate->TransferOwnershipOfContentsView());
31 }
32
CreateDefaultNonClientFrameView(Widget * widget)33 std::unique_ptr<NonClientFrameView> CreateDefaultNonClientFrameView(
34 Widget* widget) {
35 return nullptr;
36 }
37
CreateDefaultOverlayView()38 std::unique_ptr<View> CreateDefaultOverlayView() {
39 return nullptr;
40 }
41
42 } // namespace
43
44 ////////////////////////////////////////////////////////////////////////////////
45 // WidgetDelegate:
46
47 WidgetDelegate::Params::Params() = default;
48 WidgetDelegate::Params::~Params() = default;
49
WidgetDelegate()50 WidgetDelegate::WidgetDelegate()
51 : widget_initializing_callbacks_(std::make_unique<ClosureVector>()),
52 widget_initialized_callbacks_(std::make_unique<ClosureVector>()),
53 client_view_factory_(
54 base::BindOnce(&CreateDefaultClientView, base::Unretained(this))),
55 non_client_frame_view_factory_(
56 base::BindRepeating(&CreateDefaultNonClientFrameView)),
57 overlay_view_factory_(base::BindOnce(&CreateDefaultOverlayView)) {}
~WidgetDelegate()58 WidgetDelegate::~WidgetDelegate() {
59 CHECK(can_delete_this_) << "A WidgetDelegate must outlive its Widget";
60 }
61
SetCanActivate(bool can_activate)62 void WidgetDelegate::SetCanActivate(bool can_activate) {
63 can_activate_ = can_activate;
64 }
65
OnWidgetMove()66 void WidgetDelegate::OnWidgetMove() {}
67
OnDisplayChanged()68 void WidgetDelegate::OnDisplayChanged() {}
69
OnWorkAreaChanged()70 void WidgetDelegate::OnWorkAreaChanged() {}
71
OnCloseRequested(Widget::ClosedReason close_reason)72 bool WidgetDelegate::OnCloseRequested(Widget::ClosedReason close_reason) {
73 return true;
74 }
75
GetInitiallyFocusedView()76 View* WidgetDelegate::GetInitiallyFocusedView() {
77 return params_.initially_focused_view.value_or(nullptr);
78 }
79
HasConfiguredInitiallyFocusedView() const80 bool WidgetDelegate::HasConfiguredInitiallyFocusedView() const {
81 return params_.initially_focused_view.has_value();
82 }
83
AsBubbleDialogDelegate()84 BubbleDialogDelegate* WidgetDelegate::AsBubbleDialogDelegate() {
85 return nullptr;
86 }
87
AsDialogDelegate()88 DialogDelegate* WidgetDelegate::AsDialogDelegate() {
89 return nullptr;
90 }
91
CanResize() const92 bool WidgetDelegate::CanResize() const {
93 return params_.can_resize;
94 }
95
CanMaximize() const96 bool WidgetDelegate::CanMaximize() const {
97 return params_.can_maximize;
98 }
99
CanMinimize() const100 bool WidgetDelegate::CanMinimize() const {
101 return params_.can_minimize;
102 }
103
CanActivate() const104 bool WidgetDelegate::CanActivate() const {
105 return can_activate_;
106 }
107
GetModalType() const108 ui::ModalType WidgetDelegate::GetModalType() const {
109 return params_.modal_type;
110 }
111
GetAccessibleWindowRole()112 ax::mojom::Role WidgetDelegate::GetAccessibleWindowRole() {
113 return params_.accessible_role;
114 }
115
GetAccessibleWindowTitle() const116 base::string16 WidgetDelegate::GetAccessibleWindowTitle() const {
117 return params_.accessible_title.empty() ? GetWindowTitle()
118 : params_.accessible_title;
119 }
120
GetWindowTitle() const121 base::string16 WidgetDelegate::GetWindowTitle() const {
122 return params_.title;
123 }
124
ShouldShowWindowTitle() const125 bool WidgetDelegate::ShouldShowWindowTitle() const {
126 return params_.show_title;
127 }
128
ShouldCenterWindowTitleText() const129 bool WidgetDelegate::ShouldCenterWindowTitleText() const {
130 #if defined(USE_AURA)
131 return params_.center_title;
132 #else
133 return false;
134 #endif
135 }
136
ShouldShowCloseButton() const137 bool WidgetDelegate::ShouldShowCloseButton() const {
138 return params_.show_close_button;
139 }
140
GetWindowAppIcon()141 gfx::ImageSkia WidgetDelegate::GetWindowAppIcon() {
142 // Use the window icon as app icon by default.
143 return GetWindowIcon();
144 }
145
146 // Returns the icon to be displayed in the window.
GetWindowIcon()147 gfx::ImageSkia WidgetDelegate::GetWindowIcon() {
148 return params_.icon;
149 }
150
ShouldShowWindowIcon() const151 bool WidgetDelegate::ShouldShowWindowIcon() const {
152 return params_.show_icon;
153 }
154
ExecuteWindowsCommand(int command_id)155 bool WidgetDelegate::ExecuteWindowsCommand(int command_id) {
156 return false;
157 }
158
GetWindowName() const159 std::string WidgetDelegate::GetWindowName() const {
160 return std::string();
161 }
162
SaveWindowPlacement(const gfx::Rect & bounds,ui::WindowShowState show_state)163 void WidgetDelegate::SaveWindowPlacement(const gfx::Rect& bounds,
164 ui::WindowShowState show_state) {
165 std::string window_name = GetWindowName();
166 if (!window_name.empty()) {
167 ViewsDelegate::GetInstance()->SaveWindowPlacement(GetWidget(), window_name,
168 bounds, show_state);
169 }
170 }
171
GetSavedWindowPlacement(const Widget * widget,gfx::Rect * bounds,ui::WindowShowState * show_state) const172 bool WidgetDelegate::GetSavedWindowPlacement(
173 const Widget* widget,
174 gfx::Rect* bounds,
175 ui::WindowShowState* show_state) const {
176 std::string window_name = GetWindowName();
177 if (window_name.empty() ||
178 !ViewsDelegate::GetInstance()->GetSavedWindowPlacement(
179 widget, window_name, bounds, show_state))
180 return false;
181 // Try to find a display intersecting the saved bounds.
182 const auto& display =
183 display::Screen::GetScreen()->GetDisplayMatching(*bounds);
184 return display.bounds().Intersects(*bounds);
185 }
186
WidgetInitializing(Widget * widget)187 void WidgetDelegate::WidgetInitializing(Widget* widget) {
188 widget_ = widget;
189 for (auto&& callback : *widget_initializing_callbacks_)
190 std::move(callback).Run();
191 widget_initializing_callbacks_.reset();
192 OnWidgetInitializing();
193 }
194
WidgetInitialized()195 void WidgetDelegate::WidgetInitialized() {
196 for (auto&& callback : *widget_initialized_callbacks_)
197 std::move(callback).Run();
198 widget_initialized_callbacks_.reset();
199 OnWidgetInitialized();
200 }
201
WidgetDestroying()202 void WidgetDelegate::WidgetDestroying() {
203 widget_ = nullptr;
204 }
205
WindowWillClose()206 void WidgetDelegate::WindowWillClose() {
207 // TODO(ellyjones): For this and the other callback methods, establish whether
208 // any other code calls these methods. If not, DCHECK here and below that
209 // these methods are only called once.
210 for (auto&& callback : window_will_close_callbacks_)
211 std::move(callback).Run();
212 }
213
WindowClosing()214 void WidgetDelegate::WindowClosing() {
215 for (auto&& callback : window_closing_callbacks_)
216 std::move(callback).Run();
217 }
218
DeleteDelegate()219 void WidgetDelegate::DeleteDelegate() {
220 for (auto&& callback : delete_delegate_callbacks_)
221 std::move(callback).Run();
222 if (params_.owned_by_widget)
223 delete this;
224 }
225
GetWidget()226 Widget* WidgetDelegate::GetWidget() {
227 return widget_;
228 }
229
GetWidget() const230 const Widget* WidgetDelegate::GetWidget() const {
231 return widget_;
232 }
233
GetContentsView()234 View* WidgetDelegate::GetContentsView() {
235 if (unowned_contents_view_)
236 return unowned_contents_view_;
237 if (!default_contents_view_)
238 default_contents_view_ = new View;
239 return default_contents_view_;
240 }
241
TransferOwnershipOfContentsView()242 View* WidgetDelegate::TransferOwnershipOfContentsView() {
243 DCHECK(!contents_view_taken_);
244 contents_view_taken_ = true;
245 if (owned_contents_view_)
246 owned_contents_view_.release();
247 return GetContentsView();
248 }
249
CreateClientView(Widget * widget)250 ClientView* WidgetDelegate::CreateClientView(Widget* widget) {
251 DCHECK(client_view_factory_);
252 return std::move(client_view_factory_).Run(widget).release();
253 }
254
CreateNonClientFrameView(Widget * widget)255 std::unique_ptr<NonClientFrameView> WidgetDelegate::CreateNonClientFrameView(
256 Widget* widget) {
257 DCHECK(non_client_frame_view_factory_);
258 return non_client_frame_view_factory_.Run(widget);
259 }
260
CreateOverlayView()261 View* WidgetDelegate::CreateOverlayView() {
262 DCHECK(overlay_view_factory_);
263 return std::move(overlay_view_factory_).Run().release();
264 }
265
WidgetHasHitTestMask() const266 bool WidgetDelegate::WidgetHasHitTestMask() const {
267 return false;
268 }
269
GetWidgetHitTestMask(SkPath * mask) const270 void WidgetDelegate::GetWidgetHitTestMask(SkPath* mask) const {
271 DCHECK(mask);
272 }
273
ShouldDescendIntoChildForEventHandling(gfx::NativeView child,const gfx::Point & location)274 bool WidgetDelegate::ShouldDescendIntoChildForEventHandling(
275 gfx::NativeView child,
276 const gfx::Point& location) {
277 return true;
278 }
279
SetAccessibleRole(ax::mojom::Role role)280 void WidgetDelegate::SetAccessibleRole(ax::mojom::Role role) {
281 params_.accessible_role = role;
282 }
283
SetAccessibleTitle(base::string16 title)284 void WidgetDelegate::SetAccessibleTitle(base::string16 title) {
285 params_.accessible_title = std::move(title);
286 }
287
SetCanMaximize(bool can_maximize)288 void WidgetDelegate::SetCanMaximize(bool can_maximize) {
289 std::exchange(params_.can_maximize, can_maximize);
290 if (GetWidget() && params_.can_maximize != can_maximize)
291 GetWidget()->OnSizeConstraintsChanged();
292 }
293
SetCanMinimize(bool can_minimize)294 void WidgetDelegate::SetCanMinimize(bool can_minimize) {
295 std::exchange(params_.can_minimize, can_minimize);
296 if (GetWidget() && params_.can_minimize != can_minimize)
297 GetWidget()->OnSizeConstraintsChanged();
298 }
299
SetCanResize(bool can_resize)300 void WidgetDelegate::SetCanResize(bool can_resize) {
301 std::exchange(params_.can_resize, can_resize);
302 if (GetWidget() && params_.can_resize != can_resize)
303 GetWidget()->OnSizeConstraintsChanged();
304 }
305
SetOwnedByWidget(bool owned)306 void WidgetDelegate::SetOwnedByWidget(bool owned) {
307 params_.owned_by_widget = owned;
308 }
309
SetFocusTraversesOut(bool focus_traverses_out)310 void WidgetDelegate::SetFocusTraversesOut(bool focus_traverses_out) {
311 params_.focus_traverses_out = focus_traverses_out;
312 }
313
SetEnableArrowKeyTraversal(bool enable_arrow_key_traversal)314 void WidgetDelegate::SetEnableArrowKeyTraversal(
315 bool enable_arrow_key_traversal) {
316 params_.enable_arrow_key_traversal = enable_arrow_key_traversal;
317 }
318
SetIcon(const gfx::ImageSkia & icon)319 void WidgetDelegate::SetIcon(const gfx::ImageSkia& icon) {
320 params_.icon = icon;
321 if (GetWidget())
322 GetWidget()->UpdateWindowIcon();
323 }
324
SetInitiallyFocusedView(View * initially_focused_view)325 void WidgetDelegate::SetInitiallyFocusedView(View* initially_focused_view) {
326 DCHECK(!GetWidget());
327 params_.initially_focused_view = initially_focused_view;
328 }
329
SetModalType(ui::ModalType modal_type)330 void WidgetDelegate::SetModalType(ui::ModalType modal_type) {
331 DCHECK(!GetWidget());
332 params_.modal_type = modal_type;
333 }
334
SetShowCloseButton(bool show_close_button)335 void WidgetDelegate::SetShowCloseButton(bool show_close_button) {
336 params_.show_close_button = show_close_button;
337 }
338
SetShowIcon(bool show_icon)339 void WidgetDelegate::SetShowIcon(bool show_icon) {
340 params_.show_icon = show_icon;
341 if (GetWidget())
342 GetWidget()->UpdateWindowIcon();
343 }
344
SetShowTitle(bool show_title)345 void WidgetDelegate::SetShowTitle(bool show_title) {
346 params_.show_title = show_title;
347 }
348
SetTitle(const base::string16 & title)349 void WidgetDelegate::SetTitle(const base::string16& title) {
350 if (params_.title == title)
351 return;
352 params_.title = title;
353 if (GetWidget())
354 GetWidget()->UpdateWindowTitle();
355 }
356
SetTitle(int title_message_id)357 void WidgetDelegate::SetTitle(int title_message_id) {
358 SetTitle(l10n_util::GetStringUTF16(title_message_id));
359 }
360
361 #if defined(USE_AURA)
SetCenterTitle(bool center_title)362 void WidgetDelegate::SetCenterTitle(bool center_title) {
363 params_.center_title = center_title;
364 }
365 #endif
366
SetHasWindowSizeControls(bool has_controls)367 void WidgetDelegate::SetHasWindowSizeControls(bool has_controls) {
368 SetCanMaximize(has_controls);
369 SetCanMinimize(has_controls);
370 SetCanResize(has_controls);
371 }
372
RegisterWidgetInitializingCallback(base::OnceClosure callback)373 void WidgetDelegate::RegisterWidgetInitializingCallback(
374 base::OnceClosure callback) {
375 DCHECK(widget_initializing_callbacks_);
376 widget_initializing_callbacks_->emplace_back(std::move(callback));
377 }
378
RegisterWidgetInitializedCallback(base::OnceClosure callback)379 void WidgetDelegate::RegisterWidgetInitializedCallback(
380 base::OnceClosure callback) {
381 DCHECK(widget_initialized_callbacks_);
382 widget_initialized_callbacks_->emplace_back(std::move(callback));
383 }
384
RegisterWindowWillCloseCallback(base::OnceClosure callback)385 void WidgetDelegate::RegisterWindowWillCloseCallback(
386 base::OnceClosure callback) {
387 window_will_close_callbacks_.emplace_back(std::move(callback));
388 }
389
RegisterWindowClosingCallback(base::OnceClosure callback)390 void WidgetDelegate::RegisterWindowClosingCallback(base::OnceClosure callback) {
391 window_closing_callbacks_.emplace_back(std::move(callback));
392 }
393
RegisterDeleteDelegateCallback(base::OnceClosure callback)394 void WidgetDelegate::RegisterDeleteDelegateCallback(
395 base::OnceClosure callback) {
396 delete_delegate_callbacks_.emplace_back(std::move(callback));
397 }
398
SetClientViewFactory(ClientViewFactory factory)399 void WidgetDelegate::SetClientViewFactory(ClientViewFactory factory) {
400 DCHECK(!GetWidget());
401 client_view_factory_ = std::move(factory);
402 }
403
SetNonClientFrameViewFactory(NonClientFrameViewFactory factory)404 void WidgetDelegate::SetNonClientFrameViewFactory(
405 NonClientFrameViewFactory factory) {
406 DCHECK(!GetWidget());
407 non_client_frame_view_factory_ = std::move(factory);
408 }
409
SetOverlayViewFactory(OverlayViewFactory factory)410 void WidgetDelegate::SetOverlayViewFactory(OverlayViewFactory factory) {
411 DCHECK(!GetWidget());
412 overlay_view_factory_ = std::move(factory);
413 }
414
SetContentsViewImpl(View * contents)415 void WidgetDelegate::SetContentsViewImpl(View* contents) {
416 // Note: DCHECKing the ownership of contents is done in the public setters,
417 // which are inlined in the header.
418 DCHECK(!unowned_contents_view_);
419 if (!contents->owned_by_client())
420 owned_contents_view_ = base::WrapUnique(contents);
421 unowned_contents_view_ = contents;
422 }
423
424 ////////////////////////////////////////////////////////////////////////////////
425 // WidgetDelegateView:
426
WidgetDelegateView()427 WidgetDelegateView::WidgetDelegateView() {
428 // A WidgetDelegate should be deleted on DeleteDelegate.
429 set_owned_by_client();
430 SetOwnedByWidget(true);
431 }
432
433 WidgetDelegateView::~WidgetDelegateView() = default;
434
GetWidget()435 Widget* WidgetDelegateView::GetWidget() {
436 return View::GetWidget();
437 }
438
GetWidget() const439 const Widget* WidgetDelegateView::GetWidget() const {
440 return View::GetWidget();
441 }
442
GetContentsView()443 views::View* WidgetDelegateView::GetContentsView() {
444 return this;
445 }
446
447 BEGIN_METADATA(WidgetDelegateView, View)
448 END_METADATA
449
450 } // namespace views
451