Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: content/browser/android/ime_adapter_android.cc

Issue 2785543003: Revert of Let ImeAdapterAndroid have the same lifecycle as its Java peer (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "content/browser/android/ime_adapter_android.h"
6
7 #include <android/input.h>
8 #include <algorithm>
9 #include <vector>
10
11 #include "base/android/jni_android.h"
12 #include "base/android/jni_array.h"
13 #include "base/android/jni_string.h"
14 #include "base/android/scoped_java_ref.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h"
17 #include "content/browser/frame_host/interstitial_page_impl.h"
18 #include "content/browser/frame_host/render_frame_host_impl.h"
19 #include "content/browser/renderer_host/render_view_host_delegate.h"
20 #include "content/browser/renderer_host/render_widget_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_view_android.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/common/input_messages.h"
24 #include "content/common/view_messages.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/native_web_keyboard_event.h"
27 #include "content/public/browser/web_contents.h"
28 #include "jni/ImeAdapter_jni.h"
29 #include "third_party/WebKit/public/platform/WebInputEvent.h"
30 #include "third_party/WebKit/public/platform/WebTextInputType.h"
31 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
32
33 using base::android::AttachCurrentThread;
34 using base::android::ConvertJavaStringToUTF16;
35 using base::android::JavaParamRef;
36 using base::android::ScopedJavaLocalRef;
37
38 namespace content {
39 namespace {
40
41 // Maps a java KeyEvent into a NativeWebKeyboardEvent.
42 // |java_key_event| is used to maintain a globalref for KeyEvent.
43 // |type| will determine the WebInputEvent type.
44 // type, |modifiers|, |time_ms|, |key_code|, |unicode_char| is used to create
45 // WebKeyboardEvent. |key_code| is also needed ad need to treat the enter key
46 // as a key press of character \r.
47 NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
48 JNIEnv* env,
49 const base::android::JavaRef<jobject>& java_key_event,
50 int type,
51 int modifiers,
52 jlong time_ms,
53 int key_code,
54 int scan_code,
55 bool is_system_key,
56 int unicode_char) {
57 return NativeWebKeyboardEvent(env, java_key_event,
58 static_cast<blink::WebInputEvent::Type>(type),
59 modifiers, time_ms / 1000.0, key_code,
60 scan_code, unicode_char, is_system_key);
61 }
62
63 } // anonymous namespace
64
65 bool RegisterImeAdapter(JNIEnv* env) {
66 return RegisterNativesImpl(env);
67 }
68
69 jlong Init(JNIEnv* env,
70 const JavaParamRef<jobject>& obj,
71 const JavaParamRef<jobject>& jweb_contents) {
72 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
73 DCHECK(web_contents);
74 return reinterpret_cast<intptr_t>(
75 new ImeAdapterAndroid(env, obj, web_contents));
76 }
77
78 // Callback from Java to convert BackgroundColorSpan data to a
79 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
80 void AppendBackgroundColorSpan(JNIEnv*,
81 const JavaParamRef<jclass>&,
82 jlong underlines_ptr,
83 jint start,
84 jint end,
85 jint background_color) {
86 DCHECK_GE(start, 0);
87 DCHECK_GE(end, 0);
88 // Do not check |background_color|.
89 std::vector<blink::WebCompositionUnderline>* underlines =
90 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
91 underlines_ptr);
92 underlines->push_back(blink::WebCompositionUnderline(
93 static_cast<unsigned>(start), static_cast<unsigned>(end),
94 SK_ColorTRANSPARENT, false, static_cast<unsigned>(background_color)));
95 }
96
97 // Callback from Java to convert UnderlineSpan data to a
98 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
99 void AppendUnderlineSpan(JNIEnv*,
100 const JavaParamRef<jclass>&,
101 jlong underlines_ptr,
102 jint start,
103 jint end) {
104 DCHECK_GE(start, 0);
105 DCHECK_GE(end, 0);
106 std::vector<blink::WebCompositionUnderline>* underlines =
107 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
108 underlines_ptr);
109 underlines->push_back(blink::WebCompositionUnderline(
110 static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorBLACK,
111 false, SK_ColorTRANSPARENT));
112 }
113
114 ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env,
115 const JavaParamRef<jobject>& obj,
116 WebContents* web_contents)
117 : WebContentsObserver(web_contents), rwhva_(nullptr) {
118 java_ime_adapter_ = JavaObjectWeakGlobalRef(env, obj);
119 }
120
121 ImeAdapterAndroid::~ImeAdapterAndroid() {
122 JNIEnv* env = AttachCurrentThread();
123 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
124 if (!obj.is_null())
125 Java_ImeAdapter_destroy(env, obj);
126
127 UpdateRenderProcessConnection(nullptr);
128 }
129
130 RenderWidgetHostViewAndroid* ImeAdapterAndroid::GetRenderWidgetHostViewAndroid()
131 const {
132 RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView();
133 WebContentsImpl* web_contents_impl =
134 static_cast<WebContentsImpl*>(web_contents());
135 if (web_contents_impl->ShowingInterstitialPage()) {
136 rwhv = web_contents_impl->GetInterstitialPage()
137 ->GetMainFrame()
138 ->GetRenderViewHost()
139 ->GetWidget()
140 ->GetView();
141 }
142 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
143 }
144
145 void ImeAdapterAndroid::RenderViewReady() {
146 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
147
148 JNIEnv* env = AttachCurrentThread();
149 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
150 if (!obj.is_null())
151 Java_ImeAdapter_onConnectedToRenderProcess(env, obj);
152 }
153
154 void ImeAdapterAndroid::RenderViewHostChanged(RenderViewHost* old_host,
155 RenderViewHost* new_host) {
156 if (new_host) {
157 UpdateRenderProcessConnection(static_cast<RenderWidgetHostViewAndroid*>(
158 new_host->GetWidget()->GetView()));
159 } else {
160 UpdateRenderProcessConnection(nullptr);
161 }
162 }
163
164 void ImeAdapterAndroid::DidAttachInterstitialPage() {
165 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
166 }
167
168 void ImeAdapterAndroid::DidDetachInterstitialPage() {
169 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
170 }
171
172 void ImeAdapterAndroid::WebContentsDestroyed() {
173 delete this;
174 }
175
176 void ImeAdapterAndroid::UpdateRenderProcessConnection(
177 RenderWidgetHostViewAndroid* new_rwhva) {
178 if (rwhva_ == new_rwhva)
179 return;
180 if (rwhva_)
181 rwhva_->set_ime_adapter(nullptr);
182 if (new_rwhva)
183 new_rwhva->set_ime_adapter(this);
184 rwhva_ = new_rwhva;
185 }
186
187 bool ImeAdapterAndroid::SendKeyEvent(
188 JNIEnv* env,
189 const JavaParamRef<jobject>&,
190 const JavaParamRef<jobject>& original_key_event,
191 int type,
192 int modifiers,
193 jlong time_ms,
194 int key_code,
195 int scan_code,
196 bool is_system_key,
197 int unicode_char) {
198 if (!rwhva_)
199 return false;
200 NativeWebKeyboardEvent event = NativeWebKeyboardEventFromKeyEvent(
201 env, original_key_event, type, modifiers, time_ms, key_code, scan_code,
202 is_system_key, unicode_char);
203 rwhva_->SendKeyEvent(event);
204 return true;
205 }
206
207 void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
208 const JavaParamRef<jobject>& obj,
209 const JavaParamRef<jobject>& text,
210 const JavaParamRef<jstring>& text_str,
211 int relative_cursor_pos) {
212 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
213 if (!rwhi)
214 return;
215
216 base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
217
218 std::vector<blink::WebCompositionUnderline> underlines =
219 GetUnderlinesFromSpans(env, obj, text, text16);
220
221 // Default to plain underline if we didn't find any span that we care about.
222 if (underlines.empty()) {
223 underlines.push_back(blink::WebCompositionUnderline(
224 0, text16.length(), SK_ColorBLACK, false, SK_ColorTRANSPARENT));
225 }
226
227 // relative_cursor_pos is as described in the Android API for
228 // InputConnection#setComposingText, whereas the parameters for
229 // ImeSetComposition are relative to the start of the composition.
230 if (relative_cursor_pos > 0)
231 relative_cursor_pos = text16.length() + relative_cursor_pos - 1;
232
233 rwhi->ImeSetComposition(text16, underlines, gfx::Range::InvalidRange(),
234 relative_cursor_pos, relative_cursor_pos);
235 }
236
237 void ImeAdapterAndroid::CommitText(JNIEnv* env,
238 const JavaParamRef<jobject>& obj,
239 const JavaParamRef<jobject>& text,
240 const JavaParamRef<jstring>& text_str,
241 int relative_cursor_pos) {
242 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
243 if (!rwhi)
244 return;
245
246 base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
247
248 std::vector<blink::WebCompositionUnderline> underlines =
249 GetUnderlinesFromSpans(env, obj, text, text16);
250
251 // relative_cursor_pos is as described in the Android API for
252 // InputConnection#commitText, whereas the parameters for
253 // ImeConfirmComposition are relative to the end of the composition.
254 if (relative_cursor_pos > 0)
255 relative_cursor_pos--;
256 else
257 relative_cursor_pos -= text16.length();
258
259 rwhi->ImeCommitText(text16, underlines, gfx::Range::InvalidRange(),
260 relative_cursor_pos);
261 }
262
263 void ImeAdapterAndroid::FinishComposingText(JNIEnv* env,
264 const JavaParamRef<jobject>&) {
265 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
266 if (!rwhi)
267 return;
268
269 rwhi->ImeFinishComposingText(true);
270 }
271
272 void ImeAdapterAndroid::CancelComposition() {
273 JNIEnv* env = AttachCurrentThread();
274 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
275 if (!obj.is_null())
276 Java_ImeAdapter_cancelComposition(env, obj);
277 }
278
279 void ImeAdapterAndroid::FocusedNodeChanged(bool is_editable_node) {
280 JNIEnv* env = AttachCurrentThread();
281 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
282 if (!obj.is_null()) {
283 Java_ImeAdapter_focusedNodeChanged(env, obj, is_editable_node);
284 }
285 }
286
287 void ImeAdapterAndroid::SetEditableSelectionOffsets(
288 JNIEnv*,
289 const JavaParamRef<jobject>&,
290 int start,
291 int end) {
292 RenderFrameHost* rfh = GetFocusedFrame();
293 if (!rfh)
294 return;
295
296 rfh->Send(new InputMsg_SetEditableSelectionOffsets(rfh->GetRoutingID(), start,
297 end));
298 }
299
300 void ImeAdapterAndroid::SetCharacterBounds(
301 const std::vector<gfx::RectF>& character_bounds) {
302 JNIEnv* env = AttachCurrentThread();
303 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
304 if (obj.is_null())
305 return;
306
307 const size_t coordinates_array_size = character_bounds.size() * 4;
308 std::unique_ptr<float[]> coordinates_array(new float[coordinates_array_size]);
309 for (size_t i = 0; i < character_bounds.size(); ++i) {
310 const gfx::RectF& rect = character_bounds[i];
311 const size_t coordinates_array_index = i * 4;
312 coordinates_array[coordinates_array_index + 0] = rect.x();
313 coordinates_array[coordinates_array_index + 1] = rect.y();
314 coordinates_array[coordinates_array_index + 2] = rect.right();
315 coordinates_array[coordinates_array_index + 3] = rect.bottom();
316 }
317 Java_ImeAdapter_setCharacterBounds(
318 env, obj,
319 base::android::ToJavaFloatArray(env, coordinates_array.get(),
320 coordinates_array_size));
321 }
322
323 void ImeAdapterAndroid::SetComposingRegion(JNIEnv*,
324 const JavaParamRef<jobject>&,
325 int start,
326 int end) {
327 RenderFrameHost* rfh = GetFocusedFrame();
328 if (!rfh)
329 return;
330
331 std::vector<blink::WebCompositionUnderline> underlines;
332 underlines.push_back(blink::WebCompositionUnderline(
333 0, end - start, SK_ColorBLACK, false, SK_ColorTRANSPARENT));
334
335 rfh->Send(new InputMsg_SetCompositionFromExistingText(
336 rfh->GetRoutingID(), start, end, underlines));
337 }
338
339 void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*,
340 const JavaParamRef<jobject>&,
341 int before,
342 int after) {
343 RenderFrameHostImpl* rfh =
344 static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
345 if (rfh)
346 rfh->DeleteSurroundingText(before, after);
347 }
348
349 void ImeAdapterAndroid::DeleteSurroundingTextInCodePoints(
350 JNIEnv*,
351 const JavaParamRef<jobject>&,
352 int before,
353 int after) {
354 RenderFrameHostImpl* rfh =
355 static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
356 if (rfh)
357 rfh->DeleteSurroundingTextInCodePoints(before, after);
358 }
359
360 bool ImeAdapterAndroid::RequestTextInputStateUpdate(
361 JNIEnv* env,
362 const JavaParamRef<jobject>&) {
363 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
364 if (!rwhi)
365 return false;
366 rwhi->Send(new InputMsg_RequestTextInputStateUpdate(rwhi->GetRoutingID()));
367 return true;
368 }
369
370 void ImeAdapterAndroid::RequestCursorUpdate(
371 JNIEnv* env,
372 const base::android::JavaParamRef<jobject>& obj,
373 bool immediate_request,
374 bool monitor_request) {
375 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
376 if (!rwhi)
377 return;
378 rwhi->Send(new InputMsg_RequestCompositionUpdates(
379 rwhi->GetRoutingID(), immediate_request, monitor_request));
380 }
381
382 RenderWidgetHostImpl* ImeAdapterAndroid::GetFocusedWidget() {
383 DCHECK_CURRENTLY_ON(BrowserThread::UI);
384 return rwhva_ ? rwhva_->GetFocusedWidget() : nullptr;
385 }
386
387 RenderFrameHost* ImeAdapterAndroid::GetFocusedFrame() {
388 DCHECK_CURRENTLY_ON(BrowserThread::UI);
389 // We get the focused frame from the WebContents of the page. Although
390 // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way
391 // to get a RenderFrameHost from its RWH.
392 if (!rwhva_)
393 return nullptr;
394 RenderWidgetHostImpl* rwh =
395 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
396 if (!rwh || !rwh->delegate())
397 return nullptr;
398
399 if (auto* contents = rwh->delegate()->GetAsWebContents())
400 return contents->GetFocusedFrame();
401
402 return nullptr;
403 }
404
405 std::vector<blink::WebCompositionUnderline>
406 ImeAdapterAndroid::GetUnderlinesFromSpans(
407 JNIEnv* env,
408 const base::android::JavaParamRef<jobject>& obj,
409 const base::android::JavaParamRef<jobject>& text,
410 const base::string16& text16) {
411 std::vector<blink::WebCompositionUnderline> underlines;
412 // Iterate over spans in |text|, dispatch those that we care about (e.g.,
413 // BackgroundColorSpan) to a matching callback (e.g.,
414 // AppendBackgroundColorSpan()), and populate |underlines|.
415 Java_ImeAdapter_populateUnderlinesFromSpans(
416 env, obj, text, reinterpret_cast<jlong>(&underlines));
417
418 // Sort spans by |.startOffset|.
419 std::sort(underlines.begin(), underlines.end());
420
421 return underlines;
422 }
423
424 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/ime_adapter_android.h ('k') | content/browser/renderer_host/ime_adapter_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698