Bug 805162 - d. Redefine and implement Gecko to Java IME notifications in widget; r=blassey
authorJim Chen <nchen@mozilla.com>
Thu, 01 Nov 2012 16:11:02 -0400
changeset 112064 42a82ec9cc238a6a7443c910435a91e387e261c3
parent 112063 a1a6d788cd669a7fb57290f5cb48b30bfa125176
child 112065 9cb69c9fd41d331faeb607e49bd820e3019febdd
push id17398
push usernchen@mozilla.com
push dateThu, 01 Nov 2012 20:11:54 +0000
treeherdermozilla-inbound@320a9b77053b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs805162
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 805162 - d. Redefine and implement Gecko to Java IME notifications in widget; r=blassey
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/nsWindow.cpp
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -102,17 +102,16 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jNotifyIMEEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEEnabled", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");
     jNotifyIMEChange = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEChange", "(Ljava/lang/String;III)V");
     jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V");
 
     jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V");
     jEnableLocationHighAccuracy = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocationHighAccuracy", "(Z)V");
     jEnableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableSensor", "(I)V");
     jDisableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableSensor", "(I)V");
-    jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V");
     jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V");
     jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V");
     jGetHandlersForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForMimeType", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
     jGetHandlersForURL = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForURL", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
     jOpenUriExternal = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "openUriExternal", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
     jGetMimeTypeFromExtensions = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getMimeTypeFromExtensions", "(Ljava/lang/String;)Ljava/lang/String;");
     jGetExtensionFromMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getExtensionFromMimeType", "(Ljava/lang/String;)Ljava/lang/String;");
     jMoveTaskToBack = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "moveTaskToBack", "()V");
@@ -396,35 +395,16 @@ AndroidBridge::DisableSensor(int aSensor
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
     AutoLocalJNIFrame jniFrame(env, 0);
     env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, aSensorType);
 }
 
 void
-AndroidBridge::ReturnIMEQueryResult(const PRUnichar *aResult, uint32_t aLen,
-                                    int aSelStart, int aSelLen)
-{
-    ALOG_BRIDGE("AndroidBridge::ReturnIMEQueryResult");
-
-    JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env);
-    jvalue args[3];
-    args[0].l = NewJavaString(&jniFrame, aResult, aLen);
-    args[1].i = aSelStart;
-    args[2].i = aSelLen;
-    env->CallStaticVoidMethodA(mGeckoAppShellClass,
-                               jReturnIMEQueryResult, args);
-}
-
-void
 AndroidBridge::ScheduleRestart()
 {
     ALOG_BRIDGE("scheduling reboot");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -95,17 +95,17 @@ protected:
     virtual ~nsFilePickerCallback() {}
 };
 
 class AndroidBridge
 {
 public:
     enum {
         NOTIFY_IME_RESETINPUTSTATE = 0,
-        NOTIFY_IME_SETOPENSTATE = 1,
+        NOTIFY_IME_REPLY_EVENT = 1,
         NOTIFY_IME_CANCELCOMPOSITION = 2,
         NOTIFY_IME_FOCUSCHANGE = 3
     };
 
     enum {
         LAYER_CLIENT_TYPE_NONE = 0,
         LAYER_CLIENT_TYPE_GL = 2            // AndroidGeckoGLLayerClient
     };
@@ -166,18 +166,16 @@ public:
 
     void EnableLocation(bool aEnable);
     void EnableLocationHighAccuracy(bool aEnable);
 
     void EnableSensor(int aSensorType);
 
     void DisableSensor(int aSensorType);
 
-    void ReturnIMEQueryResult(const PRUnichar *aResult, uint32_t aLen, int aSelStart, int aSelLen);
-
     void NotifyXreExit();
 
     void ScheduleRestart();
 
     void SetLayerClient(JNIEnv* env, jobject jobj);
     AndroidGeckoLayerClient &GetLayerClient() { return *mLayerClient; }
 
     void SetSurfaceView(jobject jobj);
@@ -403,17 +401,16 @@ protected:
     jmethodID jNotifyIME;
     jmethodID jNotifyIMEEnabled;
     jmethodID jNotifyIMEChange;
     jmethodID jAcknowledgeEventSync;
     jmethodID jEnableLocation;
     jmethodID jEnableLocationHighAccuracy;
     jmethodID jEnableSensor;
     jmethodID jDisableSensor;
-    jmethodID jReturnIMEQueryResult;
     jmethodID jNotifyAppShellReady;
     jmethodID jNotifyXreExit;
     jmethodID jScheduleRestart;
     jmethodID jGetOutstandingDrawEvents;
     jmethodID jGetHandlersForMimeType;
     jmethodID jGetHandlersForURL;
     jmethodID jOpenUriExternal;
     jmethodID jGetMimeTypeFromExtensions;
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -648,22 +648,16 @@ nsWindow::DispatchEvent(nsGUIEvent *aEve
             MOZ_ASSERT(mIMEComposing);
             mIMEComposing = false;
             mIMEComposingText.Truncate();
             break;
         case NS_TEXT_TEXT:
             MOZ_ASSERT(mIMEComposing);
             mIMEComposingText = static_cast<nsTextEvent*>(aEvent)->theText;
             break;
-        case NS_KEY_PRESS:
-            // Sometimes the text changes after a key press do not generate notifications (see Bug 723810)
-            // Call the corresponding methods explicitly to send those changes back to Java
-            OnIMETextChange(0, 0, 0);
-            OnIMESelectionChange();
-            break;
         }
         return status;
     }
     return nsEventStatus_eIgnore;
 }
 
 NS_IMETHODIMP
 nsWindow::MakeFullScreen(bool aFullScreen)
@@ -2083,38 +2077,18 @@ nsWindow::UserActivity()
     mIdleService->ResetIdleTimeOut(0);
   }
 }
 
 NS_IMETHODIMP
 nsWindow::ResetInputState()
 {
     //ALOGIME("IME: ResetInputState: s=%d", aState);
-
-    // Cancel composition on Gecko side
-    if (mIMEComposing) {
-        nsRefPtr<nsWindow> kungFuDeathGrip(this);
-
-        nsTextEvent textEvent(true, NS_TEXT_TEXT, this);
-        InitEvent(textEvent, nullptr);
-        textEvent.theText = mIMEComposingText;
-        DispatchEvent(&textEvent);
-        mIMEComposingText.Truncate(0);
-
-        nsCompositionEvent event(true, NS_COMPOSITION_END, this);
-        InitEvent(event, nullptr);
-        DispatchEvent(&event);
-    }
-
+    RemoveIMEComposition();
     AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_RESETINPUTSTATE, 0);
-
-    // Send IME text/selection change notifications
-    OnIMETextChange(0, 0, 0);
-    OnIMESelectionChange();
-
     return NS_OK;
 }
 
 NS_IMETHODIMP_(void)
 nsWindow::SetInputContext(const InputContext& aContext,
                           const InputContextAction& aAction)
 {
     ALOGIME("IME: SetInputContext: s=0x%X, 0x%X, action=0x%X, 0x%X",
@@ -2164,17 +2138,16 @@ nsWindow::CancelIMEComposition()
 
     // Cancel composition on Gecko side
     if (mIMEComposing) {
         nsRefPtr<nsWindow> kungFuDeathGrip(this);
 
         nsTextEvent textEvent(true, NS_TEXT_TEXT, this);
         InitEvent(textEvent, nullptr);
         DispatchEvent(&textEvent);
-        mIMEComposingText.Truncate(0);
 
         nsCompositionEvent compEvent(true, NS_COMPOSITION_END, this);
         InitEvent(compEvent, nullptr);
         DispatchEvent(&compEvent);
     }
 
     AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_CANCELCOMPOSITION, 0);
     return NS_OK;
@@ -2184,75 +2157,66 @@ NS_IMETHODIMP
 nsWindow::OnIMEFocusChange(bool aFocus)
 {
     ALOGIME("IME: OnIMEFocusChange: f=%d", aFocus);
 
     AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_FOCUSCHANGE, 
                              int(aFocus));
 
     if (aFocus) {
-        OnIMETextChange(0, 0, 0);
+        OnIMETextChange(0, INT32_MAX, INT32_MAX);
         OnIMESelectionChange();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::OnIMETextChange(uint32_t aStart, uint32_t aOldEnd, uint32_t aNewEnd)
 {
+    if (mIMEMaskTextUpdate)
+        return NS_OK;
+
     ALOGIME("IME: OnIMETextChange: s=%d, oe=%d, ne=%d",
             aStart, aOldEnd, aNewEnd);
 
-    if (!mInputContext.mIMEState.mEnabled) {
-        AndroidBridge::NotifyIMEChange(nullptr, 0, 0, 0, 0);
-        return NS_OK;
-    }
-
-    // A quirk in Android makes it necessary to pass the whole text.
-    // The more efficient way would have been passing the substring from index
-    // aStart to index aNewEnd
-
     nsRefPtr<nsWindow> kungFuDeathGrip(this);
     nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, this);
     InitEvent(event, nullptr);
-    event.InitForQueryTextContent(0, UINT32_MAX);
+    event.InitForQueryTextContent(aStart, aNewEnd - aStart);
 
     DispatchEvent(&event);
     if (!event.mSucceeded)
         return NS_OK;
 
     AndroidBridge::NotifyIMEChange(event.mReply.mString.get(),
                                    event.mReply.mString.Length(),
                                    aStart, aOldEnd, aNewEnd);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::OnIMESelectionChange(void)
 {
-    ALOGIME("IME: OnIMESelectionChange");
+    if (mIMEMaskSelectionUpdate)
+        return NS_OK;
 
-    if (!mInputContext.mIMEState.mEnabled) {
-        AndroidBridge::NotifyIMEChange(nullptr, 0, 0, 0, -1);
-        return NS_OK;
-    }
+    ALOGIME("IME: OnIMESelectionChange");
 
     nsRefPtr<nsWindow> kungFuDeathGrip(this);
     nsQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, this);
     InitEvent(event, nullptr);
 
     DispatchEvent(&event);
     if (!event.mSucceeded)
         return NS_OK;
 
-    AndroidBridge::NotifyIMEChange(nullptr, 0, int(event.mReply.mOffset),
-                                   int(event.mReply.mOffset + 
-                                       event.mReply.mString.Length()), -1);
+    AndroidBridge::NotifyIMEChange(nullptr, 0, int(event.GetSelectionStart()),
+                                   int(event.GetSelectionEnd()), -1);
     return NS_OK;
 }
 
 nsIMEUpdatePreference
 nsWindow::GetIMEUpdatePreference()
 {
     return nsIMEUpdatePreference(true, true);
 }