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/single_web_contents_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 "ui/gfx/point.h"
14 #include "ui/gfx/size.h"
15 #include "ui/views/border.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/views/widget/widget_delegate.h"
18 #include "ui/views/widget/widget_observer.h"
19 #include "ui/views/window/dialog_delegate.h"
20 #include "ui/views/window/non_client_view.h"
23 #include "ui/aura/client/aura_constants.h"
24 #include "ui/aura/window.h"
25 #include "ui/wm/core/visibility_controller.h"
26 #include "ui/wm/core/window_animations.h"
27 #include "ui/wm/core/window_modality_controller.h"
30 // TODO(wittman): this code should not depend on ash.
32 #include "ash/ash_constants.h"
33 #include "ash/frame/custom_frame_view_ash.h"
34 #include "ash/shell.h"
37 using web_modal::NativeWebContentsModalDialog
;
38 using web_modal::SingleWebContentsDialogManager
;
39 using web_modal::SingleWebContentsDialogManagerDelegate
;
40 using web_modal::WebContentsModalDialogHost
;
41 using web_modal::ModalDialogHostObserver
;
45 class NativeWebContentsModalDialogManagerViews
46 : public SingleWebContentsDialogManager
,
47 public ModalDialogHostObserver
,
48 public views::WidgetObserver
{
50 NativeWebContentsModalDialogManagerViews(
51 NativeWebContentsModalDialog dialog
,
52 SingleWebContentsDialogManagerDelegate
* native_delegate
)
53 : native_delegate_(native_delegate
),
59 virtual ~NativeWebContentsModalDialogManagerViews() {
61 host_
->RemoveObserver(this);
63 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
64 it
!= observed_widgets_
.end();
66 (*it
)->RemoveObserver(this);
70 // Sets up this object to manage the dialog_. Registers for closing events
71 // in order to notify the delegate.
72 virtual void ManageDialog() {
73 views::Widget
* widget
= GetWidget(dialog());
74 widget
->AddObserver(this);
75 observed_widgets_
.insert(widget
);
76 widget
->set_movement_disabled(true);
79 // TODO(wittman): remove once the new visual style is complete
80 widget
->GetNativeWindow()->SetProperty(aura::client::kConstrainedWindowKey
,
83 wm::SetWindowVisibilityAnimationType(
84 widget
->GetNativeWindow(),
85 wm::WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
);
89 gfx::NativeView parent
= platform_util::GetParent(widget
->GetNativeView());
90 wm::SetChildWindowVisibilityChangesAnimated(parent
);
91 // No animations should get performed on the window since that will re-order
92 // the window stack which will then cause many problems.
93 if (parent
&& parent
->parent()) {
94 parent
->parent()->SetProperty(aura::client::kAnimationsDisabledKey
, true);
98 widget
->GetNativeWindow(),
99 platform_util::GetParent(widget
->GetNativeView()));
103 // SingleWebContentsDialogManager overrides
104 virtual void Show() OVERRIDE
{
105 views::Widget
* widget
= GetWidget(dialog());
106 #if defined(USE_AURA)
107 scoped_ptr
<wm::SuspendChildWindowVisibilityAnimations
> suspend
;
108 if (shown_widgets_
.find(widget
) != shown_widgets_
.end()) {
109 suspend
.reset(new wm::SuspendChildWindowVisibilityAnimations(
110 widget
->GetNativeWindow()->parent()));
113 // Host may be NULL during tab drag on Views/Win32.
115 UpdateWebContentsModalDialogPosition(widget
, host_
);
119 #if defined(USE_AURA)
120 // TODO(pkotwicz): Control the z-order of the constrained dialog via
121 // views::kHostViewKey. We will need to ensure that the parent window's
122 // shadows are below the constrained dialog in z-order when we do this.
123 shown_widgets_
.insert(widget
);
127 virtual void Hide() OVERRIDE
{
128 views::Widget
* widget
= GetWidget(dialog());
129 #if defined(USE_AURA)
130 scoped_ptr
<wm::SuspendChildWindowVisibilityAnimations
> suspend
;
131 suspend
.reset(new wm::SuspendChildWindowVisibilityAnimations(
132 widget
->GetNativeWindow()->parent()));
137 virtual void Close() OVERRIDE
{
138 GetWidget(dialog())->Close();
141 virtual void Focus() OVERRIDE
{
142 views::Widget
* widget
= GetWidget(dialog());
143 if (widget
->widget_delegate() &&
144 widget
->widget_delegate()->GetInitiallyFocusedView())
145 widget
->widget_delegate()->GetInitiallyFocusedView()->RequestFocus();
147 // We don't necessarily have a RootWindow yet.
148 if (widget
->GetNativeView()->GetRootWindow())
149 widget
->GetNativeView()->Focus();
153 virtual void Pulse() OVERRIDE
{
156 // WebContentsModalDialogHostObserver overrides
157 virtual void OnPositionRequiresUpdate() OVERRIDE
{
160 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
161 it
!= observed_widgets_
.end();
163 UpdateWebContentsModalDialogPosition(*it
, host_
);
167 virtual void OnHostDestroying() OVERRIDE
{
168 host_
->RemoveObserver(this);
172 // views::WidgetObserver overrides
174 // NOTE(wittman): OnWidgetClosing is overriden to ensure that, when the widget
175 // is explicitly closed, the destruction occurs within the same call
176 // stack. This avoids event races that lead to non-deterministic destruction
177 // ordering in e.g. the print preview dialog. OnWidgetDestroying is overridden
178 // because OnWidgetClosing is *only* invoked on explicit close, not when the
179 // widget is implicitly destroyed due to its parent being closed. This
180 // situation occurs with app windows. WidgetClosing removes the observer, so
181 // only one of these two functions is ever invoked for a given widget.
182 virtual void OnWidgetClosing(views::Widget
* widget
) OVERRIDE
{
183 WidgetClosing(widget
);
186 virtual void OnWidgetDestroying(views::Widget
* widget
) OVERRIDE
{
187 WidgetClosing(widget
);
190 virtual void HostChanged(
191 web_modal::WebContentsModalDialogHost
* new_host
) OVERRIDE
{
193 host_
->RemoveObserver(this);
197 // |host_| may be null during WebContents destruction or Win32 tab dragging.
199 host_
->AddObserver(this);
201 for (std::set
<views::Widget
*>::iterator it
= observed_widgets_
.begin();
202 it
!= observed_widgets_
.end();
204 views::Widget::ReparentNativeView((*it
)->GetNativeView(),
205 host_
->GetHostView());
208 OnPositionRequiresUpdate();
212 virtual NativeWebContentsModalDialog
dialog() OVERRIDE
{
217 static views::Widget
* GetWidget(NativeWebContentsModalDialog dialog
) {
218 views::Widget
* widget
= views::Widget::GetWidgetForNativeWindow(dialog
);
223 void WidgetClosing(views::Widget
* widget
) {
225 gfx::NativeView view
= platform_util::GetParent(widget
->GetNativeView());
226 // Allow the parent to animate again.
227 if (view
&& view
->parent())
228 view
->parent()->ClearProperty(aura::client::kAnimationsDisabledKey
);
230 widget
->RemoveObserver(this);
231 observed_widgets_
.erase(widget
);
233 #if defined(USE_AURA)
234 shown_widgets_
.erase(widget
);
237 // Will cause this object to be deleted.
238 native_delegate_
->WillClose(widget
->GetNativeView());
241 SingleWebContentsDialogManagerDelegate
* native_delegate_
;
242 NativeWebContentsModalDialog dialog_
;
243 WebContentsModalDialogHost
* host_
;
244 std::set
<views::Widget
*> observed_widgets_
;
245 std::set
<views::Widget
*> shown_widgets_
;
247 DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerViews
);
252 namespace web_modal
{
254 SingleWebContentsDialogManager
* WebContentsModalDialogManager::
255 CreateNativeWebModalManager(
256 NativeWebContentsModalDialog dialog
,
257 SingleWebContentsDialogManagerDelegate
* native_delegate
) {
258 return new NativeWebContentsModalDialogManagerViews(dialog
, native_delegate
);
261 } // namespace web_modal