Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / web_contents_modal_dialog_manager_views.cc
bloba26d04b443456ec61ebd1746296994bcab41520d
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.
5 #include <set>
7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/platform_util.h"
9 #include "components/constrained_window/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/geometry/point.h"
14 #include "ui/gfx/geometry/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"
22 #if defined(USE_AURA)
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"
28 #endif
30 using web_modal::SingleWebContentsDialogManager;
31 using web_modal::SingleWebContentsDialogManagerDelegate;
32 using web_modal::WebContentsModalDialogHost;
33 using web_modal::ModalDialogHostObserver;
35 namespace {
37 class NativeWebContentsModalDialogManagerViews
38 : public SingleWebContentsDialogManager,
39 public ModalDialogHostObserver,
40 public views::WidgetObserver {
41 public:
42 NativeWebContentsModalDialogManagerViews(
43 gfx::NativeWindow dialog,
44 SingleWebContentsDialogManagerDelegate* native_delegate)
45 : native_delegate_(native_delegate),
46 dialog_(dialog),
47 host_(NULL) {
48 ManageDialog();
51 ~NativeWebContentsModalDialogManagerViews() override {
52 if (host_)
53 host_->RemoveObserver(this);
55 for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
56 it != observed_widgets_.end();
57 ++it) {
58 (*it)->RemoveObserver(this);
62 // Sets up this object to manage the dialog_. Registers for closing events
63 // in order to notify the delegate.
64 virtual void ManageDialog() {
65 views::Widget* widget = GetWidget(dialog());
66 widget->AddObserver(this);
67 observed_widgets_.insert(widget);
68 widget->set_movement_disabled(true);
70 #if defined(USE_AURA)
71 // TODO(wittman): remove once the new visual style is complete
72 widget->GetNativeWindow()->SetProperty(aura::client::kConstrainedWindowKey,
73 true);
75 wm::SetWindowVisibilityAnimationType(
76 widget->GetNativeWindow(),
77 wm::WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE);
79 gfx::NativeView parent = platform_util::GetParent(widget->GetNativeView());
80 wm::SetChildWindowVisibilityChangesAnimated(parent);
81 // No animations should get performed on the window since that will re-order
82 // the window stack which will then cause many problems.
83 if (parent && parent->parent()) {
84 parent->parent()->SetProperty(aura::client::kAnimationsDisabledKey, true);
87 wm::SetModalParent(
88 widget->GetNativeWindow(),
89 platform_util::GetParent(widget->GetNativeView()));
90 #endif
93 // SingleWebContentsDialogManager overrides
94 void Show() override {
95 views::Widget* widget = GetWidget(dialog());
96 #if defined(USE_AURA)
97 scoped_ptr<wm::SuspendChildWindowVisibilityAnimations> suspend;
98 if (shown_widgets_.find(widget) != shown_widgets_.end()) {
99 suspend.reset(new wm::SuspendChildWindowVisibilityAnimations(
100 widget->GetNativeWindow()->parent()));
102 #endif
103 // Host may be NULL during tab drag on Views/Win32.
104 if (host_)
105 constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
106 widget->Show();
107 Focus();
109 #if defined(USE_AURA)
110 // TODO(pkotwicz): Control the z-order of the constrained dialog via
111 // views::kHostViewKey. We will need to ensure that the parent window's
112 // shadows are below the constrained dialog in z-order when we do this.
113 shown_widgets_.insert(widget);
114 #endif
117 void Hide() override {
118 views::Widget* widget = GetWidget(dialog());
119 #if defined(USE_AURA)
120 scoped_ptr<wm::SuspendChildWindowVisibilityAnimations> suspend;
121 suspend.reset(new wm::SuspendChildWindowVisibilityAnimations(
122 widget->GetNativeWindow()->parent()));
123 #endif
124 widget->Hide();
127 void Close() override { GetWidget(dialog())->Close(); }
129 void Focus() override {
130 views::Widget* widget = GetWidget(dialog());
131 if (widget->widget_delegate() &&
132 widget->widget_delegate()->GetInitiallyFocusedView())
133 widget->widget_delegate()->GetInitiallyFocusedView()->RequestFocus();
134 #if defined(USE_AURA)
135 // We don't necessarily have a RootWindow yet.
136 if (widget->GetNativeView()->GetRootWindow())
137 widget->GetNativeView()->Focus();
138 #endif
141 void Pulse() override {}
143 // WebContentsModalDialogHostObserver overrides
144 void OnPositionRequiresUpdate() override {
145 DCHECK(host_);
147 for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
148 it != observed_widgets_.end();
149 ++it) {
150 constrained_window::UpdateWebContentsModalDialogPosition(*it, host_);
154 void OnHostDestroying() override {
155 host_->RemoveObserver(this);
156 host_ = NULL;
159 // views::WidgetObserver overrides
161 // NOTE(wittman): OnWidgetClosing is overriden to ensure that, when the widget
162 // is explicitly closed, the destruction occurs within the same call
163 // stack. This avoids event races that lead to non-deterministic destruction
164 // ordering in e.g. the print preview dialog. OnWidgetDestroying is overridden
165 // because OnWidgetClosing is *only* invoked on explicit close, not when the
166 // widget is implicitly destroyed due to its parent being closed. This
167 // situation occurs with app windows. WidgetClosing removes the observer, so
168 // only one of these two functions is ever invoked for a given widget.
169 void OnWidgetClosing(views::Widget* widget) override {
170 WidgetClosing(widget);
173 void OnWidgetDestroying(views::Widget* widget) override {
174 WidgetClosing(widget);
177 void HostChanged(web_modal::WebContentsModalDialogHost* new_host) override {
178 if (host_)
179 host_->RemoveObserver(this);
181 host_ = new_host;
183 // |host_| may be null during WebContents destruction or Win32 tab dragging.
184 if (host_) {
185 host_->AddObserver(this);
187 for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
188 it != observed_widgets_.end();
189 ++it) {
190 views::Widget::ReparentNativeView((*it)->GetNativeView(),
191 host_->GetHostView());
194 OnPositionRequiresUpdate();
198 gfx::NativeWindow dialog() override { return dialog_; }
200 private:
201 static views::Widget* GetWidget(gfx::NativeWindow dialog) {
202 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(dialog);
203 DCHECK(widget);
204 return widget;
207 void WidgetClosing(views::Widget* widget) {
208 #if defined(USE_AURA)
209 gfx::NativeView view = platform_util::GetParent(widget->GetNativeView());
210 // Allow the parent to animate again.
211 if (view && view->parent())
212 view->parent()->ClearProperty(aura::client::kAnimationsDisabledKey);
213 #endif
214 widget->RemoveObserver(this);
215 observed_widgets_.erase(widget);
217 #if defined(USE_AURA)
218 shown_widgets_.erase(widget);
219 #endif
221 // Will cause this object to be deleted.
222 native_delegate_->WillClose(widget->GetNativeWindow());
225 SingleWebContentsDialogManagerDelegate* native_delegate_;
226 gfx::NativeWindow dialog_;
227 WebContentsModalDialogHost* host_;
228 std::set<views::Widget*> observed_widgets_;
229 std::set<views::Widget*> shown_widgets_;
231 DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerViews);
234 } // namespace
236 namespace web_modal {
238 SingleWebContentsDialogManager*
239 WebContentsModalDialogManager::CreateNativeWebModalManager(
240 gfx::NativeWindow dialog,
241 SingleWebContentsDialogManagerDelegate* native_delegate) {
242 return new NativeWebContentsModalDialogManagerViews(dialog, native_delegate);
245 } // namespace web_modal