web_contents_modal_dialog_manager_views.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
1c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// Use of this source code is governed by a BSD-style license that can be 3c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// found in the LICENSE file. 4c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant 5c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include <set> 6c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant 7c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "base/memory/scoped_ptr.h" 8c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "chrome/browser/platform_util.h" 9c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "chrome/browser/ui/views/constrained_window_views.h" 10c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "components/web_modal/native_web_contents_modal_dialog_manager.h" 11c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "components/web_modal/web_contents_modal_dialog_host.h" 12c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "components/web_modal/web_contents_modal_dialog_manager.h" 13c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "content/public/browser/web_contents_view.h" 14c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/gfx/point.h" 15c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/gfx/size.h" 16c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/border.h" 17c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/widget/widget.h" 18c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/widget/widget_delegate.h" 19c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/widget/widget_observer.h" 20c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/window/dialog_delegate.h" 21c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include "ui/views/window/non_client_view.h" 22c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant 23c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#if defined(USE_AURA) 24c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#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" 29#endif 30 31// TODO(wittman): this code should not depend on ash. 32#if defined(USE_ASH) 33#include "ash/ash_constants.h" 34#include "ash/shell.h" 35#include "ash/wm/custom_frame_view_ash.h" 36#endif 37 38using web_modal::NativeWebContentsModalDialog; 39using web_modal::NativeWebContentsModalDialogManager; 40using web_modal::NativeWebContentsModalDialogManagerDelegate; 41using web_modal::WebContentsModalDialogHost; 42using web_modal::WebContentsModalDialogHostObserver; 43 44namespace { 45 46class NativeWebContentsModalDialogManagerViews 47 : public NativeWebContentsModalDialogManager, 48 public WebContentsModalDialogHostObserver, 49 public views::WidgetObserver { 50 public: 51 NativeWebContentsModalDialogManagerViews( 52 NativeWebContentsModalDialogManagerDelegate* native_delegate) 53 : native_delegate_(native_delegate), 54 host_(NULL) { 55 } 56 57 virtual ~NativeWebContentsModalDialogManagerViews() { 58 if (host_) 59 host_->RemoveObserver(this); 60 61 for (std::set<views::Widget*>::iterator it = observed_widgets_.begin(); 62 it != observed_widgets_.end(); 63 ++it) { 64 (*it)->RemoveObserver(this); 65 } 66 } 67 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); 74 75#if defined(USE_AURA) 76 // TODO(wittman): remove once the new visual style is complete 77 widget->GetNativeWindow()->SetProperty(aura::client::kConstrainedWindowKey, 78 true); 79 80 if (views::DialogDelegate::UseNewStyle()) { 81 views::corewm::SetWindowVisibilityAnimationType( 82 widget->GetNativeWindow(), 83 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE); 84 } 85#endif 86 87#if defined(USE_ASH) 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); 94 } 95 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())); 101#endif 102 } 103 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())); 112 } 113#endif 114 // Host may be NULL during tab drag on Views/Win32. 115 if (host_) 116 UpdateWebContentsModalDialogPosition(widget, host_); 117 widget->Show(); 118 FocusDialog(dialog); 119 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); 125#endif 126 } 127 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())); 135 } 136#endif 137 widget->Hide(); 138 } 139 140 virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE { 141 GetWidget(dialog)->Close(); 142 } 143 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(); 149#if defined(USE_ASH) 150 // We don't necessarily have a RootWindow yet. 151 if (widget->GetNativeView()->GetRootWindow()) 152 widget->GetNativeView()->Focus(); 153#endif 154 } 155 156 virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE { 157 } 158 159 // WebContentsModalDialogHostObserver overrides 160 virtual void OnPositionRequiresUpdate() OVERRIDE { 161 DCHECK(host_); 162 163 for (std::set<views::Widget*>::iterator it = observed_widgets_.begin(); 164 it != observed_widgets_.end(); 165 ++it) { 166 UpdateWebContentsModalDialogPosition(*it, host_); 167 } 168 } 169 170 virtual void OnHostDestroying() OVERRIDE { 171 host_->RemoveObserver(this); 172 host_ = NULL; 173 } 174 175 // views::WidgetObserver overrides 176 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); 187 } 188 189 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE { 190 WidgetClosing(widget); 191 } 192 193 virtual void HostChanged( 194 web_modal::WebContentsModalDialogHost* new_host) OVERRIDE { 195 if (host_) 196 host_->RemoveObserver(this); 197 198 host_ = new_host; 199 200 if (host_) 201 host_->AddObserver(this); 202 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(); 209 ++it) { 210 views::Widget::ReparentNativeView((*it)->GetNativeView(), 211 host_->GetHostView()); 212 } 213 214 OnPositionRequiresUpdate(); 215 } 216 } 217 218 private: 219 static views::Widget* GetWidget(NativeWebContentsModalDialog dialog) { 220 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(dialog); 221 DCHECK(widget); 222 return widget; 223 } 224 225 void WidgetClosing(views::Widget* widget) { 226#if defined(USE_ASH) 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); 231#endif 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); 237#endif 238 } 239 240 NativeWebContentsModalDialogManagerDelegate* native_delegate_; 241 WebContentsModalDialogHost* host_; 242 std::set<views::Widget*> observed_widgets_; 243 std::set<views::Widget*> shown_widgets_; 244 245 DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerViews); 246}; 247 248} // namespace 249 250namespace web_modal { 251 252NativeWebContentsModalDialogManager* WebContentsModalDialogManager:: 253CreateNativeManager( 254 NativeWebContentsModalDialogManagerDelegate* native_delegate) { 255 return new NativeWebContentsModalDialogManagerViews(native_delegate); 256} 257 258} // namespace web_modal 259