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