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.
7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/platform_util.h"
9 #include "chrome/browser/ui/views/constrained_window_views.h"
10 #include "components/web_modal/native_web_contents_modal_dialog_manager.h"
11 #include "components/web_modal/web_contents_modal_dialog_host.h"
12 #include "components/web_modal/web_contents_modal_dialog_manager.h"
13 #include "content/public/browser/web_contents_view.h"
14 #include "ui/gfx/point.h"
15 #include "ui/gfx/size.h"
16 #include "ui/views/border.h"
17 #include "ui/views/widget/widget.h"
18 #include "ui/views/widget/widget_delegate.h"
19 #include "ui/views/widget/widget_observer.h"
20 #include "ui/views/window/dialog_delegate.h"
21 #include "ui/views/window/non_client_view.h"
24 #include "ui/aura/client/aura_constants.h"
25 #include "ui/aura/window.h"
26 #include "ui/views/corewm/visibility_controller.h"
27 #include "ui/views/corewm/window_animations.h"
28 #include "ui/views/corewm/window_modality_controller.h"
31 // TODO(wittman): this code should not depend on ash.
33 #include "ash/ash_constants.h"
34 #include "ash/shell.h"
35 #include "ash/wm/custom_frame_view_ash.h"
38 using web_modal::NativeWebContentsModalDialog
;
39 using web_modal::NativeWebContentsModalDialogManager
;
40 using web_modal::NativeWebContentsModalDialogManagerDelegate
;
41 using web_modal::WebContentsModalDialogHost
;
42 using web_modal::WebContentsModalDialogHostObserver
;
46 class NativeWebContentsModalDialogManagerViews
47 : public NativeWebContentsModalDialogManager
,
48 public WebContentsModalDialogHostObserver
,
49 public views::WidgetObserver
{
51 NativeWebContentsModalDialogManagerViews(
52 NativeWebContentsModalDialogManagerDelegate
* native_delegate
)
53 : native_delegate_(native_delegate
),
57 virtual ~NativeWebContentsModalDialogManagerViews() {
59 host_
->RemoveObserver(this);
61 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
62 it
!= observed_widgets_
.end();
64 (*it
)->RemoveObserver(this);
68 // NativeWebContentsModalDialogManager overrides
69 virtual void ManageDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
70 views::Widget
* widget
= GetWidget(dialog
);
71 widget
->AddObserver(this);
72 observed_widgets_
.insert(widget
);
73 widget
->set_movement_disabled(true);
76 // TODO(wittman): remove once the new visual style is complete
77 widget
->GetNativeWindow()->SetProperty(aura::client::kConstrainedWindowKey
,
80 if (views::DialogDelegate::UseNewStyle()) {
81 views::corewm::SetWindowVisibilityAnimationType(
82 widget
->GetNativeWindow(),
83 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
);
88 gfx::NativeView parent
= platform_util::GetParent(widget
->GetNativeView());
89 views::corewm::SetChildWindowVisibilityChangesAnimated(parent
);
90 // No animations should get performed on the window since that will re-order
91 // the window stack which will then cause many problems.
92 if (parent
&& parent
->parent()) {
93 parent
->parent()->SetProperty(aura::client::kAnimationsDisabledKey
, true);
96 // TODO(wittman): remove once the new visual style is complete
97 widget
->GetNativeWindow()->SetProperty(ash::kConstrainedWindowKey
, true);
98 views::corewm::SetModalParent(
99 widget
->GetNativeWindow(),
100 platform_util::GetParent(widget
->GetNativeView()));
104 virtual void ShowDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
105 views::Widget
* widget
= GetWidget(dialog
);
106 #if defined(USE_AURA)
107 scoped_ptr
<views::corewm::SuspendChildWindowVisibilityAnimations
> suspend
;
108 if (views::DialogDelegate::UseNewStyle() &&
109 shown_widgets_
.find(widget
) != shown_widgets_
.end()) {
110 suspend
.reset(new views::corewm::SuspendChildWindowVisibilityAnimations(
111 widget
->GetNativeWindow()->parent()));
114 // Host may be NULL during tab drag on Views/Win32.
116 UpdateWebContentsModalDialogPosition(widget
, host_
);
120 #if defined(USE_AURA)
121 // TODO(pkotwicz): Control the z-order of the constrained dialog via
122 // views::kHostViewKey. We will need to ensure that the parent window's
123 // shadows are below the constrained dialog in z-order when we do this.
124 shown_widgets_
.insert(widget
);
128 virtual void HideDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
129 views::Widget
* widget
= GetWidget(dialog
);
130 #if defined(USE_AURA)
131 scoped_ptr
<views::corewm::SuspendChildWindowVisibilityAnimations
> suspend
;
132 if (views::DialogDelegate::UseNewStyle()) {
133 suspend
.reset(new views::corewm::SuspendChildWindowVisibilityAnimations(
134 widget
->GetNativeWindow()->parent()));
140 virtual void CloseDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
141 GetWidget(dialog
)->Close();
144 virtual void FocusDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
145 views::Widget
* widget
= GetWidget(dialog
);
146 if (widget
->widget_delegate() &&
147 widget
->widget_delegate()->GetInitiallyFocusedView())
148 widget
->widget_delegate()->GetInitiallyFocusedView()->RequestFocus();
150 // We don't necessarily have a RootWindow yet.
151 if (widget
->GetNativeView()->GetRootWindow())
152 widget
->GetNativeView()->Focus();
156 virtual void PulseDialog(NativeWebContentsModalDialog dialog
) OVERRIDE
{
159 // WebContentsModalDialogHostObserver overrides
160 virtual void OnPositionRequiresUpdate() OVERRIDE
{
163 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
164 it
!= observed_widgets_
.end();
166 UpdateWebContentsModalDialogPosition(*it
, host_
);
170 virtual void OnHostDestroying() OVERRIDE
{
171 host_
->RemoveObserver(this);
175 // views::WidgetObserver overrides
177 // NOTE(wittman): OnWidgetClosing is overriden to ensure that, when the widget
178 // is explicitly closed, the destruction occurs within the same call
179 // stack. This avoids event races that lead to non-deterministic destruction
180 // ordering in e.g. the print preview dialog. OnWidgetDestroying is overridden
181 // because OnWidgetClosing is *only* invoked on explicit close, not when the
182 // widget is implicitly destroyed due to its parent being closed. This
183 // situation occurs with app windows. WidgetClosing removes the observer, so
184 // only one of these two functions is ever invoked for a given widget.
185 virtual void OnWidgetClosing(views::Widget
* widget
) OVERRIDE
{
186 WidgetClosing(widget
);
189 virtual void OnWidgetDestroying(views::Widget
* widget
) OVERRIDE
{
190 WidgetClosing(widget
);
193 virtual void HostChanged(
194 web_modal::WebContentsModalDialogHost
* new_host
) OVERRIDE
{
196 host_
->RemoveObserver(this);
201 host_
->AddObserver(this);
203 // Old-style dialogs are parented to the web contents view and don't need
204 // reparenting. The host_ may be null during tab drag under Views/Win32 or
205 // when destroying the WebContents.
206 if (views::DialogDelegate::UseNewStyle() && host_
) {
207 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
208 it
!= observed_widgets_
.end();
210 views::Widget::ReparentNativeView((*it
)->GetNativeView(),
211 host_
->GetHostView());
214 OnPositionRequiresUpdate();
219 static views::Widget
* GetWidget(NativeWebContentsModalDialog dialog
) {
220 views::Widget
* widget
= views::Widget::GetWidgetForNativeWindow(dialog
);
225 void WidgetClosing(views::Widget
* widget
) {
227 gfx::NativeView view
= platform_util::GetParent(widget
->GetNativeView());
228 // Allow the parent to animate again.
229 if (view
&& view
->parent())
230 view
->parent()->ClearProperty(aura::client::kAnimationsDisabledKey
);
232 widget
->RemoveObserver(this);
233 native_delegate_
->WillClose(widget
->GetNativeView());
234 observed_widgets_
.erase(widget
);
235 #if defined(USE_AURA)
236 shown_widgets_
.erase(widget
);
240 NativeWebContentsModalDialogManagerDelegate
* native_delegate_
;
241 WebContentsModalDialogHost
* host_
;
242 std::set
<views::Widget
*> observed_widgets_
;
243 std::set
<views::Widget
*> shown_widgets_
;
245 DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerViews
);
250 namespace web_modal
{
252 NativeWebContentsModalDialogManager
* WebContentsModalDialogManager::
254 NativeWebContentsModalDialogManagerDelegate
* native_delegate
) {
255 return new NativeWebContentsModalDialogManagerViews(native_delegate
);
258 } // namespace web_modal