Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / components / constrained_window / constrained_window_views.cc
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 "components/constrained_window/constrained_window_views.h"
6
7 #include <algorithm>
8
9 #include "components/constrained_window/constrained_window_views_client.h"
10 #include "components/web_modal/popup_manager.h"
11 #include "components/web_modal/web_contents_modal_dialog_host.h"
12 #include "ui/views/border.h"
13 #include "ui/views/widget/widget.h"
14 #include "ui/views/widget/widget_observer.h"
15 #include "ui/views/window/dialog_delegate.h"
16
17 using web_modal::ModalDialogHost;
18 using web_modal::ModalDialogHostObserver;
19
20 namespace {
21
22 ConstrainedWindowViewsClient* constrained_window_views_client = NULL;
23
24 // The name of a key to store on the window handle to associate
25 // WidgetModalDialogHostObserverViews with the Widget.
26 const char* const kWidgetModalDialogHostObserverViewsKey =
27     "__WIDGET_MODAL_DIALOG_HOST_OBSERVER_VIEWS__";
28
29 // Applies positioning changes from the ModalDialogHost to the Widget.
30 class WidgetModalDialogHostObserverViews
31     : public views::WidgetObserver,
32       public ModalDialogHostObserver {
33  public:
34   WidgetModalDialogHostObserverViews(ModalDialogHost* host,
35                                      views::Widget* target_widget,
36                                      const char *const native_window_property)
37       : host_(host),
38         target_widget_(target_widget),
39         native_window_property_(native_window_property) {
40     DCHECK(host_);
41     DCHECK(target_widget_);
42     host_->AddObserver(this);
43     target_widget_->AddObserver(this);
44   }
45
46   ~WidgetModalDialogHostObserverViews() override {
47     if (host_)
48       host_->RemoveObserver(this);
49     target_widget_->RemoveObserver(this);
50     target_widget_->SetNativeWindowProperty(native_window_property_, NULL);
51   }
52
53   // WidgetObserver overrides
54   void OnWidgetClosing(views::Widget* widget) override { delete this; }
55
56   // WebContentsModalDialogHostObserver overrides
57   void OnPositionRequiresUpdate() override {
58     UpdateWidgetModalDialogPosition(target_widget_, host_);
59   }
60
61   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(WidgetModalDialogHostObserverViews);
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 // static
102 void SetConstrainedWindowViewsClient(
103     scoped_ptr<ConstrainedWindowViewsClient> new_client) {
104   delete constrained_window_views_client;
105   constrained_window_views_client = new_client.release();
106 }
107
108 void UpdateWebContentsModalDialogPosition(
109     views::Widget* widget,
110     web_modal::WebContentsModalDialogHost* dialog_host) {
111   gfx::Size size = widget->GetRootView()->GetPreferredSize();
112   gfx::Size max_size = dialog_host->GetMaximumDialogSize();
113   // Enlarge the max size by the top border, as the dialog will be shifted
114   // outside the area specified by the dialog host by this amount later.
115   views::Border* border =
116       widget->non_client_view()->frame_view()->border();
117   // Border may be null during widget initialization.
118   if (border)
119     max_size.Enlarge(0, border->GetInsets().top());
120   size.SetToMin(max_size);
121   UpdateModalDialogPosition(widget, dialog_host, size);
122 }
123
124 void UpdateWidgetModalDialogPosition(views::Widget* widget,
125                                      web_modal::ModalDialogHost* dialog_host) {
126   UpdateModalDialogPosition(widget, dialog_host,
127                             widget->GetRootView()->GetPreferredSize());
128 }
129
130 views::Widget* ShowWebModalDialogViews(
131     views::WidgetDelegate* dialog,
132     content::WebContents* initiator_web_contents) {
133   DCHECK(constrained_window_views_client);
134   // For embedded WebContents, use the embedder's WebContents for constrained
135   // window.
136   content::WebContents* web_contents = constrained_window_views_client->
137       GetEmbedderWebContents(initiator_web_contents);
138   views::Widget* widget = CreateWebModalDialogViews(dialog, web_contents);
139   web_modal::PopupManager* popup_manager =
140       web_modal::PopupManager::FromWebContents(web_contents);
141   popup_manager->ShowModalDialog(widget->GetNativeWindow(), web_contents);
142   return widget;
143 }
144
145 views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog,
146                                          content::WebContents* web_contents) {
147   DCHECK_EQ(ui::MODAL_TYPE_CHILD, dialog->GetModalType());
148   web_modal::PopupManager* popup_manager =
149       web_modal::PopupManager::FromWebContents(web_contents);
150   const gfx::NativeView parent = popup_manager->GetHostView();
151   return views::DialogDelegate::CreateDialogWidget(dialog, NULL, parent);
152 }
153
154 // TODO(gbillock): Replace this with PopupManager calls.
155 views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
156                                              gfx::NativeView parent) {
157   DCHECK_NE(ui::MODAL_TYPE_CHILD, dialog->GetModalType());
158   DCHECK_NE(ui::MODAL_TYPE_NONE, dialog->GetModalType());
159
160   views::Widget* widget =
161       views::DialogDelegate::CreateDialogWidget(dialog, NULL, parent);
162   if (!dialog->UseNewStyleForThisDialog())
163     return widget;
164   DCHECK(constrained_window_views_client);
165   ModalDialogHost* host = constrained_window_views_client->
166       GetModalDialogHost(parent);
167   if (host) {
168     DCHECK_EQ(parent, host->GetHostView());
169     ModalDialogHostObserver* dialog_host_observer =
170         new WidgetModalDialogHostObserverViews(
171             host, widget, kWidgetModalDialogHostObserverViewsKey);
172     dialog_host_observer->OnPositionRequiresUpdate();
173   }
174   return widget;
175 }