1 // Copyright 2014 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 "base/basictypes.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "mojo/application/application_runner_chromium.h"
9 #include "mojo/common/common_type_converters.h"
10 #include "mojo/examples/window_manager/window_manager.mojom.h"
11 #include "mojo/public/c/system/main.h"
12 #include "mojo/public/cpp/application/application_connection.h"
13 #include "mojo/public/cpp/application/application_delegate.h"
14 #include "mojo/public/cpp/application/application_impl.h"
15 #include "mojo/public/cpp/application/connect.h"
16 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
17 #include "mojo/services/public/cpp/view_manager/view.h"
18 #include "mojo/services/public/cpp/view_manager/view_manager.h"
19 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h"
20 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
21 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
22 #include "mojo/views/native_widget_view_manager.h"
23 #include "mojo/views/views_init.h"
24 #include "ui/aura/client/focus_client.h"
25 #include "ui/aura/window.h"
26 #include "ui/events/event.h"
27 #include "ui/views/background.h"
28 #include "ui/views/controls/textfield/textfield.h"
29 #include "ui/views/controls/textfield/textfield_controller.h"
30 #include "ui/views/focus/focus_manager.h"
31 #include "ui/views/layout/layout_manager.h"
32 #include "ui/views/widget/widget.h"
33 #include "ui/views/widget/widget_delegate.h"
34 #include "ui/views/widget/widget_observer.h"
40 class BrowserLayoutManager
: public views::LayoutManager
{
42 BrowserLayoutManager() {}
43 virtual ~BrowserLayoutManager() {}
46 // Overridden from views::LayoutManager:
47 virtual void Layout(views::View
* host
) OVERRIDE
{
48 // Browser view has one child, a text input field.
49 DCHECK_EQ(1, host
->child_count());
50 views::View
* text_field
= host
->child_at(0);
51 gfx::Size ps
= text_field
->GetPreferredSize();
52 text_field
->SetBoundsRect(gfx::Rect(host
->width(), ps
.height()));
54 virtual gfx::Size
GetPreferredSize(const views::View
* host
) const OVERRIDE
{
58 DISALLOW_COPY_AND_ASSIGN(BrowserLayoutManager
);
61 // KeyboardManager handles notifying the windowmanager when views are focused.
62 // To use create one and KeyboardManager will take care of all other details.
64 // TODO(sky): it would be nice if this were put in NativeWidgetViewManager, but
65 // that requires NativeWidgetViewManager to take an IWindowManager. That may be
66 // desirable anyway...
68 : public views::FocusChangeListener
,
69 public ui::EventHandler
,
70 public views::WidgetObserver
{
72 KeyboardManager(views::Widget
* widget
,
73 IWindowManager
* window_manager
,
76 window_manager_(window_manager
),
80 widget_
->GetFocusManager()->AddFocusChangeListener(this);
81 widget_
->AddObserver(this);
82 widget_
->GetNativeView()->AddPostTargetHandler(this);
86 virtual ~KeyboardManager() {
87 widget_
->GetFocusManager()->RemoveFocusChangeListener(this);
88 widget_
->GetNativeView()->RemovePostTargetHandler(this);
89 widget_
->RemoveObserver(this);
94 void ShowKeyboard(views::View
* view
) {
95 if (focused_view_
== view
)
98 const gfx::Rect bounds_in_widget
=
99 view
->ConvertRectToWidget(gfx::Rect(view
->bounds().size()));
100 last_view_id_
= view_
->id();
101 window_manager_
->ShowKeyboard(last_view_id_
,
102 Rect::From(bounds_in_widget
));
103 // TODO(sky): listen for view to be removed.
104 focused_view_
= view
;
107 void HideKeyboard() {
111 window_manager_
->HideKeyboard(last_view_id_
);
113 focused_view_
= NULL
;
116 // views::FocusChangeListener:
117 virtual void OnWillChangeFocus(views::View
* focused_before
,
118 views::View
* focused_now
) OVERRIDE
{
120 virtual void OnDidChangeFocus(views::View
* focused_before
,
121 views::View
* focused_now
) OVERRIDE
{
122 if (focused_view_
&& focused_now
!= focused_view_
)
127 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
128 views::View
* focused_now
= widget_
->GetFocusManager()->GetFocusedView();
130 focused_now
->GetClassName() == views::Textfield::kViewClassName
&&
131 (event
->flags() & ui::EF_FROM_TOUCH
) != 0) {
132 ShowKeyboard(focused_now
);
136 // views::WidgetObserver:
137 virtual void OnWidgetDestroying(views::Widget
* widget
) OVERRIDE
{
141 views::Widget
* widget_
;
142 IWindowManager
* window_manager_
;
145 views::View
* focused_view_
;
147 DISALLOW_COPY_AND_ASSIGN(KeyboardManager
);
150 // This is the basics of creating a views widget with a textfield.
152 class Browser
: public ApplicationDelegate
,
153 public ViewManagerDelegate
,
154 public views::TextfieldController
,
155 public ViewObserver
{
158 : view_manager_(NULL
),
164 root_
->RemoveObserver(this);
168 // Overridden from ApplicationDelegate:
169 virtual void Initialize(ApplicationImpl
* app
) MOJO_OVERRIDE
{
170 view_manager_client_factory_
.reset(
171 new ViewManagerClientFactory(app
->shell(), this));
172 views_init_
.reset(new ViewsInit
);
173 app
->ConnectToService("mojo:mojo_window_manager", &window_manager_
);
176 virtual bool ConfigureIncomingConnection(ApplicationConnection
* connection
)
178 connection
->AddService(view_manager_client_factory_
.get());
182 void CreateWidget(View
* view
) {
183 views::Textfield
* textfield
= new views::Textfield
;
184 textfield
->set_controller(this);
186 views::WidgetDelegateView
* widget_delegate
= new views::WidgetDelegateView
;
187 widget_delegate
->GetContentsView()->set_background(
188 views::Background::CreateSolidBackground(SK_ColorBLUE
));
189 widget_delegate
->GetContentsView()->AddChildView(textfield
);
190 widget_delegate
->GetContentsView()->SetLayoutManager(
191 new BrowserLayoutManager
);
193 widget_
= new views::Widget
;
194 views::Widget::InitParams
params(
195 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
196 params
.native_widget
= new NativeWidgetViewManager(widget_
, view
);
197 params
.delegate
= widget_delegate
;
198 params
.bounds
= gfx::Rect(view
->bounds().width(), view
->bounds().height());
199 widget_
->Init(params
);
200 // KeyboardManager handles deleting itself when the widget is destroyed.
201 new KeyboardManager(widget_
, window_manager_
.get(), view
);
203 textfield
->RequestFocus();
206 // ViewManagerDelegate:
207 virtual void OnEmbed(ViewManager
* view_manager
,
209 ServiceProviderImpl
* exported_services
,
210 scoped_ptr
<ServiceProvider
> imported_services
) OVERRIDE
{
211 // TODO: deal with OnEmbed() being invoked multiple times.
212 ConnectToService(imported_services
.get(), &navigator_host_
);
213 view_manager_
= view_manager
;
215 root_
->AddObserver(this);
219 virtual void OnViewManagerDisconnected(
220 ViewManager
* view_manager
) OVERRIDE
{
221 DCHECK_EQ(view_manager_
, view_manager
);
222 view_manager_
= NULL
;
223 base::MessageLoop::current()->Quit();
226 // views::TextfieldController:
227 virtual bool HandleKeyEvent(views::Textfield
* sender
,
228 const ui::KeyEvent
& key_event
) OVERRIDE
{
229 if (key_event
.key_code() == ui::VKEY_RETURN
) {
230 GURL
url(sender
->text());
231 printf("User entered this URL: %s\n", url
.spec().c_str());
232 URLRequestPtr
request(URLRequest::New());
233 request
->url
= String::From(url
);
234 navigator_host_
->RequestNavigate(TARGET_NEW_NODE
, request
.Pass());
240 virtual void OnViewFocusChanged(View
* gained_focus
,
241 View
* lost_focus
) OVERRIDE
{
242 aura::client::FocusClient
* focus_client
=
243 aura::client::GetFocusClient(widget_
->GetNativeView());
244 if (lost_focus
== root_
)
245 focus_client
->FocusWindow(NULL
);
246 else if (gained_focus
== root_
)
247 focus_client
->FocusWindow(widget_
->GetNativeView());
249 virtual void OnViewDestroyed(View
* view
) OVERRIDE
{
250 DCHECK_EQ(root_
, view
);
251 view
->RemoveObserver(this);
255 scoped_ptr
<ViewsInit
> views_init_
;
257 ViewManager
* view_manager_
;
258 scoped_ptr
<ViewManagerClientFactory
> view_manager_client_factory_
;
260 views::Widget
* widget_
;
261 NavigatorHostPtr navigator_host_
;
262 IWindowManagerPtr window_manager_
;
264 DISALLOW_COPY_AND_ASSIGN(Browser
);
267 } // namespace examples
270 MojoResult
MojoMain(MojoHandle shell_handle
) {
271 mojo::ApplicationRunnerChromium
runner(new mojo::examples::Browser
);
272 return runner
.Run(shell_handle
);