OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/ui/views/constrained_window_views.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "chrome/browser/ui/browser_finder.h" | |
10 #include "components/web_modal/popup_manager.h" | |
11 #include "components/web_modal/web_contents_modal_dialog_host.h" | |
12 #include "extensions/browser/guest_view/guest_view_base.h" | |
13 #include "ui/views/border.h" | |
14 #include "ui/views/widget/widget.h" | |
15 #include "ui/views/widget/widget_observer.h" | |
16 #include "ui/views/window/dialog_delegate.h" | |
17 | |
18 using web_modal::ModalDialogHost; | |
19 using web_modal::ModalDialogHostObserver; | |
20 | |
21 namespace { | |
22 // The name of a key to store on the window handle to associate | |
23 // BrowserModalDialogHostObserverViews with the Widget. | |
24 const char* const kBrowserModalDialogHostObserverViewsKey = | |
25 "__BROWSER_MODAL_DIALOG_HOST_OBSERVER_VIEWS__"; | |
26 | |
27 // Applies positioning changes from the ModalDialogHost to the Widget. | |
28 class BrowserModalDialogHostObserverViews | |
29 : public views::WidgetObserver, | |
30 public ModalDialogHostObserver { | |
31 public: | |
32 BrowserModalDialogHostObserverViews(ModalDialogHost* host, | |
33 views::Widget* target_widget, | |
34 const char *const native_window_property) | |
35 : host_(host), | |
36 target_widget_(target_widget), | |
37 native_window_property_(native_window_property) { | |
38 DCHECK(host_); | |
39 DCHECK(target_widget_); | |
40 host_->AddObserver(this); | |
41 target_widget_->AddObserver(this); | |
42 } | |
43 | |
44 virtual ~BrowserModalDialogHostObserverViews() { | |
45 if (host_) | |
46 host_->RemoveObserver(this); | |
47 target_widget_->RemoveObserver(this); | |
48 target_widget_->SetNativeWindowProperty(native_window_property_, NULL); | |
49 } | |
50 | |
51 // WidgetObserver overrides | |
52 virtual void OnWidgetClosing(views::Widget* widget) override { | |
53 delete this; | |
54 } | |
55 | |
56 // WebContentsModalDialogHostObserver overrides | |
57 virtual void OnPositionRequiresUpdate() override { | |
58 UpdateBrowserModalDialogPosition(target_widget_, host_); | |
59 } | |
60 | |
61 virtual void OnHostDestroying() override { | |
62 host_->RemoveObserver(this); | |
63 host_ = NULL; | |
64 } | |
65 | |
66 private: | |
67 ModalDialogHost* host_; | |
68 views::Widget* target_widget_; | |
69 const char* const native_window_property_; | |
70 | |
71 DISALLOW_COPY_AND_ASSIGN(BrowserModalDialogHostObserverViews); | |
72 }; | |
73 | |
74 void UpdateModalDialogPosition(views::Widget* widget, | |
75 web_modal::ModalDialogHost* dialog_host, | |
76 const gfx::Size& size) { | |
77 // Do not forcibly update the dialog widget position if it is being dragged. | |
78 if (widget->HasCapture()) | |
79 return; | |
80 | |
81 gfx::Point position = dialog_host->GetDialogPosition(size); | |
82 views::Border* border = widget->non_client_view()->frame_view()->border(); | |
83 // Border may be null during widget initialization. | |
84 if (border) { | |
85 // Align the first row of pixels inside the border. This is the apparent | |
86 // top of the dialog. | |
87 position.set_y(position.y() - border->GetInsets().top()); | |
88 } | |
89 | |
90 if (widget->is_top_level()) { | |
91 position += | |
92 views::Widget::GetWidgetForNativeView(dialog_host->GetHostView())-> | |
93 GetClientAreaBoundsInScreen().OffsetFromOrigin(); | |
94 } | |
95 | |
96 widget->SetBounds(gfx::Rect(position, size)); | |
97 } | |
98 | |
99 } // namespace | |
100 | |
101 void UpdateWebContentsModalDialogPosition( | |
102 views::Widget* widget, | |
103 web_modal::WebContentsModalDialogHost* dialog_host) { | |
104 gfx::Size size = widget->GetRootView()->GetPreferredSize(); | |
105 gfx::Size max_size = dialog_host->GetMaximumDialogSize(); | |
106 // Enlarge the max size by the top border, as the dialog will be shifted | |
107 // outside the area specified by the dialog host by this amount later. | |
108 views::Border* border = | |
109 widget->non_client_view()->frame_view()->border(); | |
110 // Border may be null during widget initialization. | |
111 if (border) | |
112 max_size.Enlarge(0, border->GetInsets().top()); | |
113 size.SetToMin(max_size); | |
114 UpdateModalDialogPosition(widget, dialog_host, size); | |
115 } | |
116 | |
117 void UpdateBrowserModalDialogPosition(views::Widget* widget, | |
118 web_modal::ModalDialogHost* dialog_host) { | |
119 UpdateModalDialogPosition(widget, dialog_host, | |
120 widget->GetRootView()->GetPreferredSize()); | |
121 } | |
122 | |
123 views::Widget* ShowWebModalDialogViews( | |
124 views::WidgetDelegate* dialog, | |
125 content::WebContents* initiator_web_contents) { | |
126 extensions::GuestViewBase* guest_view = | |
127 extensions::GuestViewBase::FromWebContents(initiator_web_contents); | |
128 // For embedded WebContents, use the embedder's WebContents for constrained | |
129 // window. | |
130 content::WebContents* web_contents = | |
131 guest_view && guest_view->embedder_web_contents() ? | |
132 guest_view->embedder_web_contents() : initiator_web_contents; | |
133 views::Widget* widget = CreateWebModalDialogViews(dialog, web_contents); | |
134 web_modal::PopupManager* popup_manager = | |
135 web_modal::PopupManager::FromWebContents(web_contents); | |
136 popup_manager->ShowModalDialog(widget->GetNativeWindow(), web_contents); | |
137 return widget; | |
138 } | |
139 | |
140 views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog, | |
141 content::WebContents* web_contents) { | |
142 DCHECK_EQ(ui::MODAL_TYPE_CHILD, dialog->GetModalType()); | |
143 web_modal::PopupManager* popup_manager = | |
144 web_modal::PopupManager::FromWebContents(web_contents); | |
145 const gfx::NativeWindow parent = popup_manager->GetHostView(); | |
146 return views::DialogDelegate::CreateDialogWidget(dialog, NULL, parent); | |
147 } | |
148 | |
149 // TODO(gbillock): Replace this with PopupManager calls. | |
150 views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog, | |
151 gfx::NativeWindow parent) { | |
152 views::Widget* widget = | |
153 views::DialogDelegate::CreateDialogWidget(dialog, NULL, parent); | |
154 if (!dialog->UseNewStyleForThisDialog()) | |
155 return widget; | |
156 | |
157 // Get the browser dialog management and hosting components from |parent|. | |
158 Browser* browser = chrome::FindBrowserWithWindow(parent); | |
159 if (browser) { | |
160 ChromeWebModalDialogManagerDelegate* manager = browser; | |
161 ModalDialogHost* host = manager->GetWebContentsModalDialogHost(); | |
162 DCHECK_EQ(parent, host->GetHostView()); | |
163 ModalDialogHostObserver* dialog_host_observer = | |
164 new BrowserModalDialogHostObserverViews( | |
165 host, widget, kBrowserModalDialogHostObserverViewsKey); | |
166 dialog_host_observer->OnPositionRequiresUpdate(); | |
167 } | |
168 return widget; | |
169 } | |
OLD | NEW |