1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/constrained_window/native_web_contents_modal_dialog_manager_views.h"
9 #include "components/constrained_window/constrained_window_views.h"
10 #include "components/web_modal/web_contents_modal_dialog_host.h"
11 #include "components/web_modal/web_contents_modal_dialog_manager.h"
12 #include "ui/gfx/geometry/point.h"
13 #include "ui/gfx/geometry/size.h"
14 #include "ui/views/border.h"
15 #include "ui/views/widget/widget.h"
16 #include "ui/views/widget/widget_delegate.h"
17 #include "ui/views/window/dialog_delegate.h"
18 #include "ui/views/window/non_client_view.h"
21 #include "ui/aura/client/aura_constants.h"
22 #include "ui/aura/window.h"
23 #include "ui/wm/core/visibility_controller.h"
24 #include "ui/wm/core/window_animations.h"
25 #include "ui/wm/core/window_modality_controller.h"
28 using web_modal::SingleWebContentsDialogManager;
29 using web_modal::SingleWebContentsDialogManagerDelegate;
30 using web_modal::WebContentsModalDialogHost;
31 using web_modal::ModalDialogHostObserver;
33 namespace constrained_window {
35 NativeWebContentsModalDialogManagerViews::
36 NativeWebContentsModalDialogManagerViews(
37 gfx::NativeWindow dialog,
38 SingleWebContentsDialogManagerDelegate* native_delegate)
39 : native_delegate_(native_delegate), dialog_(dialog) {
43 NativeWebContentsModalDialogManagerViews::
44 ~NativeWebContentsModalDialogManagerViews() {
46 host_->RemoveObserver(this);
48 for (auto* widget : observed_widgets_)
49 widget->RemoveObserver(this);
50 CHECK(!IsInObserverList());
53 void NativeWebContentsModalDialogManagerViews::ManageDialog() {
54 views::Widget* widget = GetWidget(dialog());
55 widget->AddObserver(this);
56 observed_widgets_.insert(widget);
57 widget->set_movement_disabled(true);
60 // TODO(wittman): remove once the new visual style is complete
61 widget->GetNativeWindow()->SetProperty(aura::client::kConstrainedWindowKey,
64 wm::SetWindowVisibilityAnimationType(
65 widget->GetNativeWindow(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE);
67 gfx::NativeView parent = widget->GetNativeView()->parent();
68 wm::SetChildWindowVisibilityChangesAnimated(parent);
69 // No animations should get performed on the window since that will re-order
70 // the window stack which will then cause many problems.
71 if (parent->parent()) {
72 parent->parent()->SetProperty(aura::client::kAnimationsDisabledKey, true);
75 wm::SetModalParent(widget->GetNativeWindow(),
76 native_delegate_->GetWebContents()->GetNativeView());
80 // SingleWebContentsDialogManager:
82 bool NativeWebContentsModalDialogManagerViews::IsActive() const {
83 return GetWidget(dialog_)->IsActive();
86 void NativeWebContentsModalDialogManagerViews::Show() {
87 // The host destroying means the dialogs will be destroyed in short order.
88 // Avoid showing dialogs at this point as the necessary native window
89 // services may not be present.
93 views::Widget* widget = GetWidget(dialog());
95 std::unique_ptr<wm::SuspendChildWindowVisibilityAnimations> suspend;
96 if (shown_widgets_.find(widget) != shown_widgets_.end()) {
97 suspend = std::make_unique<wm::SuspendChildWindowVisibilityAnimations>(
98 widget->GetNativeWindow()->parent());
103 constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
104 if (host_->ShouldActivateDialog()) {
108 widget->ShowInactive();
111 #if defined(USE_AURA)
112 // TODO(pkotwicz): Control the z-order of the constrained dialog via
113 // views::kHostViewKey. We will need to ensure that the parent window's
114 // shadows are below the constrained dialog in z-order when we do this.
115 shown_widgets_.insert(widget);
118 #if !defined(USE_AURA)
119 // Don't re-animate when switching tabs. Note this is done on Mac only after
120 // the initial Show() call above, and then "sticks" for later calls.
121 // TODO(tapted): Consolidate this codepath with Aura.
122 widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_HIDE);
126 void NativeWebContentsModalDialogManagerViews::Hide() {
127 views::Widget* widget = GetWidget(dialog());
128 #if defined(USE_AURA)
129 auto suspend = std::make_unique<wm::SuspendChildWindowVisibilityAnimations>(
130 widget->GetNativeWindow()->parent());
135 void NativeWebContentsModalDialogManagerViews::Close() {
136 GetWidget(dialog())->Close();
139 void NativeWebContentsModalDialogManagerViews::Focus() {
140 views::Widget* widget = GetWidget(dialog());
141 if (widget->widget_delegate() &&
142 widget->widget_delegate()->GetInitiallyFocusedView())
143 widget->widget_delegate()->GetInitiallyFocusedView()->RequestFocus();
144 #if defined(USE_AURA)
145 // We don't necessarily have a RootWindow yet.
146 if (widget->GetNativeView()->GetRootWindow())
147 widget->GetNativeView()->Focus();
151 void NativeWebContentsModalDialogManagerViews::Pulse() {}
153 // web_modal::ModalDialogHostObserver:
155 void NativeWebContentsModalDialogManagerViews::OnPositionRequiresUpdate() {
158 for (auto* widget : observed_widgets_)
159 constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
162 void NativeWebContentsModalDialogManagerViews::OnHostDestroying() {
163 host_->RemoveObserver(this);
165 host_destroying_ = true;
168 // views::WidgetObserver:
170 void NativeWebContentsModalDialogManagerViews::OnWidgetClosing(
171 views::Widget* widget) {
172 WidgetClosing(widget);
175 void NativeWebContentsModalDialogManagerViews::OnWidgetDestroying(
176 views::Widget* widget) {
177 WidgetClosing(widget);
180 void NativeWebContentsModalDialogManagerViews::HostChanged(
181 WebContentsModalDialogHost* new_host) {
183 host_->RemoveObserver(this);
187 // |host_| may be null during WebContents destruction.
189 host_->AddObserver(this);
191 for (auto* widget : observed_widgets_) {
192 views::Widget::ReparentNativeView(widget->GetNativeView(),
193 host_->GetHostView());
196 OnPositionRequiresUpdate();
200 gfx::NativeWindow NativeWebContentsModalDialogManagerViews::dialog() {
204 views::Widget* NativeWebContentsModalDialogManagerViews::GetWidget(
205 gfx::NativeWindow dialog) {
206 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(dialog);
211 void NativeWebContentsModalDialogManagerViews::WidgetClosing(
212 views::Widget* widget) {
213 #if defined(USE_AURA)
214 gfx::NativeView view = widget->GetNativeView()->parent();
215 // Allow the parent to animate again.
216 if (view && view->parent())
217 view->parent()->ClearProperty(aura::client::kAnimationsDisabledKey);
219 widget->RemoveObserver(this);
220 observed_widgets_.erase(widget);
222 #if defined(USE_AURA)
223 shown_widgets_.erase(widget);
226 // Will cause this object to be deleted.
227 native_delegate_->WillClose(widget->GetNativeWindow());
230 } // namespace constrained_window