Skip to content

Commit 1f257c7

Browse files
authored
Merge pull request #834 from wordpress-mobile/fix/ime-iob-fix
Fix/ime iob fix
2 parents a6c634c + 2169aff commit 1f257c7

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ import android.view.MotionEvent
4848
import android.view.View
4949
import android.view.WindowManager
5050
import android.view.inputmethod.BaseInputConnection
51+
import android.view.inputmethod.EditorInfo
52+
import android.view.inputmethod.InputConnection
5153
import android.widget.CheckBox
5254
import android.widget.EditText
5355
import android.widget.Toast
@@ -70,6 +72,7 @@ import org.wordpress.aztec.handlers.ListHandler
7072
import org.wordpress.aztec.handlers.ListItemHandler
7173
import org.wordpress.aztec.handlers.PreformatHandler
7274
import org.wordpress.aztec.handlers.QuoteHandler
75+
import org.wordpress.aztec.ime.EditorInfoUtils
7376
import org.wordpress.aztec.plugins.IAztecPlugin
7477
import org.wordpress.aztec.plugins.IToolbarButton
7578
import org.wordpress.aztec.source.Format
@@ -118,6 +121,7 @@ import org.wordpress.aztec.watchers.event.text.BeforeTextChangedEventData
118121
import org.wordpress.aztec.watchers.event.text.OnTextChangedEventData
119122
import org.wordpress.aztec.watchers.event.text.TextWatcherEvent
120123
import org.xml.sax.Attributes
124+
import java.lang.ref.WeakReference
121125
import java.security.MessageDigest
122126
import java.security.NoSuchAlgorithmException
123127
import java.util.ArrayList
@@ -291,6 +295,9 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
291295

292296
private var focusOnVisible = true
293297

298+
var inputConnectionRef: WeakReference<InputConnection>? = null
299+
var inputConnectionEditorInfo: EditorInfo? = null
300+
294301
interface OnSelectionChangedListener {
295302
fun onSelectionChanged(selStart: Int, selEnd: Int)
296303
}
@@ -660,6 +667,45 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
660667
}
661668
}
662669

670+
override fun onCreateInputConnection(outAttrs: EditorInfo) : InputConnection {
671+
// limiting the reuseInputConnection fix for Anroid 8.0.0 for now
672+
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
673+
return handleReuseInputConnection(outAttrs)
674+
}
675+
676+
return super.onCreateInputConnection(outAttrs)
677+
}
678+
679+
private fun handleReuseInputConnection(outAttrs: EditorInfo) : InputConnection {
680+
// initialize inputConnectionEditorInfo
681+
if (inputConnectionEditorInfo == null) {
682+
inputConnectionEditorInfo = outAttrs
683+
}
684+
685+
// now init the InputConnection, or replace if EditorInfo contains anything different
686+
if (inputConnectionRef?.get() == null || !EditorInfoUtils.areEditorInfosTheSame(outAttrs, inputConnectionEditorInfo!!)) {
687+
// we have a new InputConnection to create, save the new EditorInfo data and create it
688+
// we make a copy of the parameters being received, because super.onCreateInputConnection may make changes
689+
// to EditorInfo params being sent to it, and we want to preserve the same data we received in order
690+
// to compare.
691+
// (see https://android.googlesource.com/platform/frameworks/base/+/jb-mr0-release/core/java/android/widget/
692+
// TextView.java#5404)
693+
inputConnectionEditorInfo = EditorInfoUtils.copyEditorInfo(outAttrs)
694+
val localInputConnection = super.onCreateInputConnection(outAttrs)
695+
if (localInputConnection == null) {
696+
// in case super returns null, let's just observe the base implementation, no need to make
697+
// an InputConnectionWrapper of a null target
698+
return localInputConnection
699+
}
700+
// if non null, wrap the new InputConnection around our wrapper (used for logging purposes only)
701+
//inputConnection = AztecTextInputConnectionWrapper(localInputConnection, this)
702+
inputConnectionRef = WeakReference(localInputConnection)
703+
}
704+
705+
// return the existing inputConnection
706+
return inputConnectionRef?.get()!!
707+
}
708+
663709
override fun onRestoreInstanceState(state: Parcelable?) {
664710
disableTextChangedListener()
665711

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.wordpress.aztec.ime
2+
3+
import android.os.Build
4+
import android.view.inputmethod.EditorInfo
5+
import java.util.Arrays
6+
7+
object EditorInfoUtils {
8+
@JvmStatic
9+
fun areEditorInfosTheSame(ed1: EditorInfo, ed2: EditorInfo): Boolean {
10+
if (ed1 == ed2) {
11+
return true
12+
}
13+
14+
if (ed1.actionId == ed2.actionId
15+
&& (ed1.actionLabel != null && ed1.actionLabel.equals(ed2.actionLabel) || ed1.actionLabel == null && ed2.actionLabel == null)
16+
&& ed1.inputType == ed2.inputType
17+
&& ed1.imeOptions == ed2.imeOptions
18+
&& (ed1.privateImeOptions != null && ed1.privateImeOptions.equals(ed2.privateImeOptions) || ed1.privateImeOptions == null && ed2.privateImeOptions == null)
19+
&& ed1.initialSelStart == ed2.initialSelStart
20+
&& ed1.initialSelEnd == ed2.initialSelEnd
21+
&& ed1.initialCapsMode == ed2.initialCapsMode
22+
&& ed1.fieldId == ed2.fieldId
23+
) {
24+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
25+
// specific comparisons here
26+
if (ed1.contentMimeTypes != null && ed2.contentMimeTypes != null) {
27+
return Arrays.equals(ed1.contentMimeTypes, ed2.contentMimeTypes)
28+
}
29+
}
30+
return true
31+
}
32+
return false
33+
}
34+
35+
@JvmStatic
36+
fun copyEditorInfo(ed1: EditorInfo) : EditorInfo {
37+
val copy = EditorInfo()
38+
copy.actionId = ed1.actionId
39+
copy.actionLabel = ed1.actionLabel?.toString()
40+
copy.inputType = ed1.inputType
41+
copy.imeOptions = ed1.imeOptions
42+
copy.privateImeOptions = ed1.privateImeOptions?.toString()
43+
copy.initialSelStart = ed1.initialSelStart
44+
copy.initialSelEnd = ed1.initialSelEnd
45+
copy.initialCapsMode = ed1.initialCapsMode
46+
copy.fieldId = ed1.fieldId
47+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
48+
// specific comparisons here
49+
if (ed1.contentMimeTypes != null) {
50+
copy.contentMimeTypes = Arrays.copyOf(ed1.contentMimeTypes, ed1.contentMimeTypes.size)
51+
}
52+
}
53+
return copy
54+
}
55+
}

aztec/src/main/kotlin/org/wordpress/aztec/plugins/CssUnderlinePlugin.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ class CssUnderlinePlugin : ISpanPostprocessor, ISpanPreprocessor {
4141
if (hiddenSpan.TAG == SPAN_TAG) {
4242
val parentStyle = hiddenSpan.attributes.getValue(CssStyleFormatter.STYLE_ATTRIBUTE)
4343
val childStyle = calypsoUnderlineSpan.attributes.getValue(CssStyleFormatter.STYLE_ATTRIBUTE)
44-
hiddenSpan.attributes.setValue(CssStyleFormatter.STYLE_ATTRIBUTE, CssStyleFormatter.mergeStyleAttributes(parentStyle, childStyle))
44+
if (parentStyle != null && childStyle != null) {
45+
hiddenSpan.attributes.setValue(CssStyleFormatter.STYLE_ATTRIBUTE, CssStyleFormatter.mergeStyleAttributes(parentStyle, childStyle))
46+
}
4547

4648
// remove the extra child span
4749
spannable.removeSpan(calypsoUnderlineSpan)

0 commit comments

Comments
 (0)