OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 <stdio.h> | |
6 #include <string> | |
7 | |
8 #include "base/at_exit.h" | |
9 #include "base/command_line.h" | |
10 #include "base/files/file_path.h" | |
11 #include "base/i18n/icu_util.h" | |
12 #include "base/macros.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/path_service.h" | |
15 #include "mojo/aura/screen_mojo.h" | |
16 #include "mojo/aura/window_tree_host_mojo.h" | |
17 #include "mojo/examples/launcher/launcher.mojom.h" | |
18 #include "mojo/public/cpp/application/application.h" | |
19 #include "mojo/public/cpp/gles2/gles2.h" | |
20 #include "mojo/public/cpp/system/core.h" | |
21 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h" | |
22 #include "mojo/services/native_viewport/native_viewport.mojom.h" | |
23 #include "ui/aura/client/aura_constants.h" | |
24 #include "ui/aura/client/default_capture_client.h" | |
25 #include "ui/aura/client/window_tree_client.h" | |
26 #include "ui/aura/env.h" | |
27 #include "ui/aura/test/test_focus_client.h" | |
28 #include "ui/aura/window.h" | |
29 #include "ui/aura/window_delegate.h" | |
30 #include "ui/aura/window_event_dispatcher.h" | |
31 #include "ui/aura/window_tree_host.h" | |
32 #include "ui/base/hit_test.h" | |
33 #include "ui/base/ime/input_method.h" | |
34 #include "ui/base/ime/input_method_delegate.h" | |
35 #include "ui/base/ime/input_method_factory.h" | |
36 #include "ui/base/resource/resource_bundle.h" | |
37 #include "ui/gfx/canvas.h" | |
38 #include "ui/views/background.h" | |
39 #include "ui/views/border.h" | |
40 #include "ui/views/controls/textfield/textfield.h" | |
41 #include "ui/views/controls/textfield/textfield_controller.h" | |
42 #include "ui/views/layout/fill_layout.h" | |
43 #include "ui/views/view.h" | |
44 #include "ui/views/widget/widget.h" | |
45 #include "ui/wm/core/default_activation_client.h" | |
46 #include "url/gurl.h" | |
47 | |
48 #if defined(WIN32) | |
49 #if !defined(CDECL) | |
50 #define CDECL __cdecl | |
51 #endif | |
52 #define LAUNCHER_EXPORT __declspec(dllexport) | |
53 #else | |
54 #define CDECL | |
55 #define LAUNCHER_EXPORT __attribute__((visibility("default"))) | |
56 #endif | |
57 | |
58 namespace mojo { | |
59 namespace examples { | |
60 | |
61 class MinimalInputEventFilter : public ui::internal::InputMethodDelegate, | |
62 public ui::EventHandler { | |
63 public: | |
64 explicit MinimalInputEventFilter(aura::Window* root) | |
65 : root_(root), | |
66 input_method_(ui::CreateInputMethod(this, | |
67 gfx::kNullAcceleratedWidget)) { | |
68 ui::InitializeInputMethod(); | |
69 input_method_->Init(true); | |
70 root_->AddPreTargetHandler(this); | |
71 root_->SetProperty(aura::client::kRootWindowInputMethodKey, | |
72 input_method_.get()); | |
73 } | |
74 | |
75 virtual ~MinimalInputEventFilter() { | |
76 root_->RemovePreTargetHandler(this); | |
77 root_->SetProperty(aura::client::kRootWindowInputMethodKey, | |
78 static_cast<ui::InputMethod*>(NULL)); | |
79 } | |
80 | |
81 private: | |
82 // ui::EventHandler: | |
83 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { | |
84 // See the comment in InputMethodEventFilter::OnKeyEvent() for details. | |
85 if (event->IsTranslated()) { | |
86 event->SetTranslated(false); | |
87 } else { | |
88 if (input_method_->DispatchKeyEvent(*event)) | |
89 event->StopPropagation(); | |
90 } | |
91 } | |
92 | |
93 // ui::internal::InputMethodDelegate: | |
94 virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE { | |
95 // See the comment in InputMethodEventFilter::DispatchKeyEventPostIME() for | |
96 // details. | |
97 ui::KeyEvent aura_event(event); | |
98 aura_event.SetTranslated(true); | |
99 ui::EventDispatchDetails details = | |
100 root_->GetHost()->dispatcher()->OnEventFromSource(&aura_event); | |
101 return aura_event.handled() || details.dispatcher_destroyed; | |
102 } | |
103 | |
104 aura::Window* root_; | |
105 scoped_ptr<ui::InputMethod> input_method_; | |
106 | |
107 DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter); | |
108 }; | |
109 | |
110 class LauncherWindowTreeClient : public aura::client::WindowTreeClient { | |
111 public: | |
112 explicit LauncherWindowTreeClient(aura::Window* window) : window_(window) { | |
113 aura::client::SetWindowTreeClient(window_, this); | |
114 } | |
115 | |
116 virtual ~LauncherWindowTreeClient() { | |
117 aura::client::SetWindowTreeClient(window_, NULL); | |
118 } | |
119 | |
120 // Overridden from aura::client::WindowTreeClient: | |
121 virtual aura::Window* GetDefaultParent(aura::Window* context, | |
122 aura::Window* window, | |
123 const gfx::Rect& bounds) OVERRIDE { | |
124 return window_; | |
125 } | |
126 | |
127 private: | |
128 aura::Window* window_; | |
129 | |
130 DISALLOW_COPY_AND_ASSIGN(LauncherWindowTreeClient); | |
131 }; | |
132 | |
133 // Called when the user has submitted a URL by pressing Enter. | |
134 class URLReceiver { | |
135 public: | |
136 virtual void OnURLEntered(const std::string& url_text) = 0; | |
137 | |
138 protected: | |
139 virtual ~URLReceiver() {} | |
140 }; | |
141 | |
142 class LauncherController : public views::TextfieldController { | |
143 public: | |
144 explicit LauncherController(URLReceiver* url_receiver) | |
145 : url_receiver_(url_receiver) {} | |
146 | |
147 void InitInWindow(aura::Window* parent) { | |
148 views::Widget* widget = new views::Widget; | |
149 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); | |
150 params.parent = parent; | |
151 params.bounds = parent->bounds(); | |
152 params.activatable = views::Widget::InitParams::ACTIVATABLE_YES; | |
153 widget->Init(params); | |
154 | |
155 views::View* container = new views::View; | |
156 container->set_background( | |
157 views::Background::CreateSolidBackground(SK_ColorYELLOW)); | |
158 container->SetBorder( | |
159 views::Border::CreateEmptyBorder(10, 10, 10, 10)); | |
160 container->SetLayoutManager(new views::FillLayout); | |
161 widget->SetContentsView(container); | |
162 | |
163 views::Textfield* textfield = new views::Textfield; | |
164 textfield->set_controller(this); | |
165 container->AddChildView(textfield); | |
166 textfield->RequestFocus(); | |
167 | |
168 container->Layout(); | |
169 | |
170 widget->Show(); | |
171 } | |
172 | |
173 private: | |
174 // Overridden from views::TextfieldController: | |
175 virtual bool HandleKeyEvent(views::Textfield* sender, | |
176 const ui::KeyEvent& key_event) OVERRIDE { | |
177 if (key_event.key_code() == ui::VKEY_RETURN) { | |
178 GURL url(sender->text()); | |
179 printf("Enter pressed with URL: %s\n", url.spec().c_str()); | |
180 url_receiver_->OnURLEntered(url.spec()); | |
181 } | |
182 return false; | |
183 } | |
184 | |
185 URLReceiver* url_receiver_; | |
186 | |
187 DISALLOW_COPY_AND_ASSIGN(LauncherController); | |
188 }; | |
189 | |
190 class LauncherImpl : public InterfaceImpl<Launcher>, | |
191 public URLReceiver { | |
192 public: | |
193 explicit LauncherImpl(Application* app) | |
194 : app_(app), | |
195 launcher_controller_(this), | |
196 pending_show_(false) { | |
197 screen_.reset(ScreenMojo::Create()); | |
198 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get()); | |
199 | |
200 NativeViewportPtr viewport; | |
201 app_->ConnectTo("mojo:mojo_native_viewport_service", &viewport); | |
202 | |
203 window_tree_host_.reset(new WindowTreeHostMojo( | |
204 viewport.Pass(), gfx::Rect(50, 50, 450, 60), | |
205 base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this)))); | |
206 } | |
207 | |
208 private: | |
209 // Overridden from Launcher: | |
210 virtual void Show() OVERRIDE { | |
211 if (!window_tree_host_.get()) { | |
212 pending_show_ = true; | |
213 return; | |
214 } | |
215 window_tree_host_->Show(); | |
216 } | |
217 virtual void Hide() OVERRIDE { | |
218 window_tree_host_->Hide(); | |
219 } | |
220 | |
221 // Overridden from URLReceiver: | |
222 virtual void OnURLEntered(const std::string& url_text) OVERRIDE { | |
223 client()->OnURLEntered(String::From(url_text)); | |
224 } | |
225 | |
226 void HostContextCreated() { | |
227 window_tree_host_->InitHost(); | |
228 window_tree_host_->window()->SetBounds(gfx::Rect(450, 60)); | |
229 | |
230 focus_client_.reset(new aura::test::TestFocusClient()); | |
231 aura::client::SetFocusClient(window_tree_host_->window(), | |
232 focus_client_.get()); | |
233 new wm::DefaultActivationClient(window_tree_host_->window()); | |
234 capture_client_.reset( | |
235 new aura::client::DefaultCaptureClient(window_tree_host_->window())); | |
236 ime_filter_.reset(new MinimalInputEventFilter(window_tree_host_->window())); | |
237 | |
238 window_tree_client_.reset( | |
239 new LauncherWindowTreeClient(window_tree_host_->window())); | |
240 | |
241 launcher_controller_.InitInWindow(window_tree_host_->window()); | |
242 | |
243 if (pending_show_) { | |
244 pending_show_ = false; | |
245 Show(); | |
246 } | |
247 } | |
248 | |
249 Application* app_; | |
250 scoped_ptr<ScreenMojo> screen_; | |
251 scoped_ptr<LauncherWindowTreeClient> window_tree_client_; | |
252 scoped_ptr<aura::client::FocusClient> focus_client_; | |
253 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_; | |
254 scoped_ptr<ui::EventHandler> ime_filter_; | |
255 | |
256 LauncherController launcher_controller_; | |
257 | |
258 scoped_ptr<aura::WindowTreeHost> window_tree_host_; | |
259 | |
260 bool pending_show_; | |
261 }; | |
262 | |
263 } // namespace examples | |
264 } // namespace mojo | |
265 | |
266 extern "C" LAUNCHER_EXPORT MojoResult CDECL MojoMain( | |
267 MojoHandle service_provider_handle) { | |
268 base::CommandLine::Init(0, NULL); | |
269 base::AtExitManager at_exit; | |
270 base::i18n::InitializeICU(); | |
271 | |
272 base::FilePath pak_dir; | |
273 PathService::Get(base::DIR_MODULE, &pak_dir); | |
274 base::FilePath pak_file; | |
275 pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak")); | |
276 ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file); | |
277 | |
278 base::MessageLoop loop; | |
279 mojo::GLES2Initializer gles2; | |
280 | |
281 // TODO(beng): This crashes in a DCHECK on X11 because this thread's | |
282 // MessageLoop is not of TYPE_UI. I think we need a way to build | |
283 // Aura that doesn't define platform-specific stuff. | |
284 aura::Env::CreateInstance(true); | |
285 | |
286 mojo::Application app(service_provider_handle); | |
287 app.AddService<mojo::examples::LauncherImpl>(&app); | |
288 | |
289 loop.Run(); | |
290 return MOJO_RESULT_OK; | |
291 } | |
OLD | NEW |