diff --git a/app/src/main/java/com/osfans/trime/core/Rime.kt b/app/src/main/java/com/osfans/trime/core/Rime.kt index db6f9b1872..00d2051cd3 100644 --- a/app/src/main/java/com/osfans/trime/core/Rime.kt +++ b/app/src/main/java/com/osfans/trime/core/Rime.kt @@ -257,7 +257,7 @@ class Rime : RimeApi, RimeLifecycleOwner { @JvmStatic val composingText: String - get() = inputContext?.commitTextPreview ?: "" + get() = inputContext?.composition?.commitTextPreview ?: "" @JvmStatic fun isVoidKeycode(keycode: Int): Boolean { diff --git a/app/src/main/java/com/osfans/trime/core/RimeProto.kt b/app/src/main/java/com/osfans/trime/core/RimeProto.kt index cebb25f902..60e28305c8 100644 --- a/app/src/main/java/com/osfans/trime/core/RimeProto.kt +++ b/app/src/main/java/com/osfans/trime/core/RimeProto.kt @@ -3,13 +3,13 @@ package com.osfans.trime.core class RimeProto { data class Commit(val text: String?) - data class Candidate(val text: String, val comment: String?) + data class Candidate(val text: String, val comment: String?, val label: String) data class Context( val composition: Composition, val menu: Menu, - val commitTextPreview: String?, - val selectLabels: Array, + val input: String, + val caretPos: Int, ) { data class Composition( val length: Int = 0, @@ -17,12 +17,11 @@ class RimeProto { private val _selStart: Int = 0, private val _selEnd: Int = 0, val preedit: String? = null, + val commitTextPreview: String? = null, ) { - val selStart: Int = - if (preedit.isNullOrEmpty()) 0 else String(preedit.toByteArray(), 0, _selStart).length + val selStart: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _selStart).length } - val selEnd: Int = - if (preedit.isNullOrEmpty()) 0 else String(preedit.toByteArray(), 0, _selEnd).length + val selEnd: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _selEnd).length } } data class Menu( @@ -31,6 +30,8 @@ class RimeProto { val isLastPage: Boolean = false, val highlightedCandidateIndex: Int = 0, val candidates: Array = arrayOf(), + val selectKeys: String? = null, + val selectLabels: Array = arrayOf(), ) { override fun equals(other: Any?): Boolean { if (this === other) return true @@ -43,6 +44,8 @@ class RimeProto { if (isLastPage != other.isLastPage) return false if (highlightedCandidateIndex != other.highlightedCandidateIndex) return false if (!candidates.contentEquals(other.candidates)) return false + if (selectKeys != other.selectKeys) return false + if (!selectLabels.contentEquals(other.selectLabels)) return false return true } @@ -53,31 +56,11 @@ class RimeProto { result = 31 * result + isLastPage.hashCode() result = 31 * result + highlightedCandidateIndex result = 31 * result + candidates.contentHashCode() + result = 31 * result + (selectKeys?.hashCode() ?: 0) + result = 31 * result + selectLabels.contentHashCode() return result } } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Context - - if (composition != other.composition) return false - if (menu != other.menu) return false - if (commitTextPreview != other.commitTextPreview) return false - if (!selectLabels.contentEquals(other.selectLabels)) return false - - return true - } - - override fun hashCode(): Int { - var result = composition.hashCode() - result = 31 * result + menu.hashCode() - result = 31 * result + (commitTextPreview?.hashCode() ?: 0) - result = 31 * result + selectLabels.contentHashCode() - return result - } } data class Status( diff --git a/app/src/main/java/com/osfans/trime/ime/composition/Composition.kt b/app/src/main/java/com/osfans/trime/ime/composition/Composition.kt index d9e71bf977..247cceb0ef 100644 --- a/app/src/main/java/com/osfans/trime/ime/composition/Composition.kt +++ b/app/src/main/java/com/osfans/trime/ime/composition/Composition.kt @@ -289,7 +289,6 @@ class Composition(context: Context, attrs: AttributeSet?) : TextView(context, at private fun SpannableStringBuilder.buildSpannedCandidates( m: CompositionComponent, candidates: Array, - selectLabels: Array, offset: Int, ) { if (candidates.isEmpty()) return @@ -297,7 +296,7 @@ class Composition(context: Context, attrs: AttributeSet?) : TextView(context, at val alignmentSpan = alignmentSpan(m.align) for ((i, candidate) in candidates.withIndex()) { val text = String.format(m.candidate, candidate.text) - val label = String.format(m.label, selectLabels[i]) + val label = String.format(m.label, candidate.label) if (i >= maxCount) break if (!allPhrases && i >= offset) break if (allPhrases && text.length < minCheckLength) { @@ -437,7 +436,6 @@ class Composition(context: Context, attrs: AttributeSet?) : TextView(context, at buildSpannedCandidates( component, candidates, - ctx.selectLabels, startNum, ) } diff --git a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt index 76193b3a88..c7b5db4d02 100644 --- a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt +++ b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt @@ -1047,9 +1047,9 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { val ic = currentInputConnection ?: return val text = when (prefs.keyboard.inlinePreedit) { - InlinePreeditMode.PREVIEW -> ctx.commitTextPreview ?: "" + InlinePreeditMode.PREVIEW -> ctx.composition.commitTextPreview ?: "" InlinePreeditMode.COMPOSITION -> ctx.composition.preedit ?: "" - InlinePreeditMode.INPUT -> Rime.getRimeRawInput() ?: "" + InlinePreeditMode.INPUT -> ctx.input InlinePreeditMode.NONE -> "" } if (ic.getSelectedText(0).isNullOrEmpty() || text.isNotEmpty()) { diff --git a/app/src/main/jni/librime_jni/jni-utils.h b/app/src/main/jni/librime_jni/jni-utils.h index 6b830d0276..f37b2e4a09 100644 --- a/app/src/main/jni/librime_jni/jni-utils.h +++ b/app/src/main/jni/librime_jni/jni-utils.h @@ -220,7 +220,8 @@ class GlobalRefSingleton { CandidateProto = reinterpret_cast(env->NewGlobalRef( env->FindClass("com/osfans/trime/core/RimeProto$Candidate"))); CandidateProtoInit = env->GetMethodID( - CandidateProto, "", "(Ljava/lang/String;Ljava/lang/String;)V"); + CandidateProto, "", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); CommitProto = reinterpret_cast(env->NewGlobalRef( env->FindClass("com/osfans/trime/core/RimeProto$Commit"))); @@ -233,20 +234,22 @@ class GlobalRefSingleton { ContextProto, "", "(Lcom/osfans/trime/core/RimeProto$Context$Composition;Lcom/osfans/" "trime/core/" - "RimeProto$Context$Menu;Ljava/lang/String;[Ljava/lang/String;)V"); + "RimeProto$Context$Menu;Ljava/lang/String;I)V"); CompositionProto = reinterpret_cast(env->NewGlobalRef( env->FindClass("com/osfans/trime/core/RimeProto$Context$Composition"))); - CompositionProtoInit = env->GetMethodID(CompositionProto, "", - "(IIIILjava/lang/String;)V"); + CompositionProtoInit = + env->GetMethodID(CompositionProto, "", + "(IIIILjava/lang/String;Ljava/lang/String;)V"); CompositionProtoDefault = env->GetMethodID(CompositionProto, "", "()V"); MenuProto = reinterpret_cast(env->NewGlobalRef( env->FindClass("com/osfans/trime/core/RimeProto$Context$Menu"))); - MenuProtoInit = - env->GetMethodID(MenuProto, "", - "(IIZI[Lcom/osfans/trime/core/RimeProto$Candidate;)V"); + MenuProtoInit = env->GetMethodID( + MenuProto, "", + "(IIZI[Lcom/osfans/trime/core/RimeProto$Candidate;Ljava/lang/" + "String;[Ljava/lang/String;)V"); MenuProtoDefault = env->GetMethodID(MenuProto, "", "()V"); StatusProto = reinterpret_cast(env->NewGlobalRef( diff --git a/app/src/main/jni/librime_jni/objconv.h b/app/src/main/jni/librime_jni/objconv.h index 09dc1298ab..fb71339231 100644 --- a/app/src/main/jni/librime_jni/objconv.h +++ b/app/src/main/jni/librime_jni/objconv.h @@ -14,7 +14,8 @@ inline jobject rimeCommitToJObject(JNIEnv *env, const RimeCommit &commit) { *JString(env, commit.text)); } -inline jobject rimeContextToJObject(JNIEnv *env, const RimeContext &context) { +inline jobject rimeContextToJObject(JNIEnv *env, const RimeContext &context, + std::string_view input, int caretPos) { jobject composition = env->NewObject(GlobalRef->CompositionProto, GlobalRef->CompositionProtoDefault); if (RIME_STRUCT_HAS_MEMBER(context, context.composition)) { @@ -22,18 +23,19 @@ inline jobject rimeContextToJObject(JNIEnv *env, const RimeContext &context) { GlobalRef->CompositionProto, GlobalRef->CompositionProtoInit, context.composition.length, context.composition.cursor_pos, context.composition.sel_start, context.composition.sel_end, - *JString(env, context.composition.preedit)); + *JString(env, context.composition.preedit), + *JString(env, context.commit_text_preview)); } jobject menu = env->NewObject(GlobalRef->MenuProto, GlobalRef->MenuProtoDefault); - auto destSelectLabels = env->NewObjectArray(0, GlobalRef->String, nullptr); if (RIME_STRUCT_HAS_MEMBER(context, context.menu)) { const auto &src = context.menu; const auto numCandidates = src.num_candidates; const auto selectKeysSize = src.select_keys ? strlen(src.select_keys) : 0; - destSelectLabels = - env->NewObjectArray(src.num_candidates, GlobalRef->String, nullptr); + auto destSelectLabels = JRef( + env, + env->NewObjectArray(src.num_candidates, GlobalRef->String, nullptr)); auto destCandidates = JRef( env, env->NewObjectArray(src.num_candidates, GlobalRef->CandidateProto, nullptr)); @@ -52,18 +54,19 @@ inline jobject rimeContextToJObject(JNIEnv *env, const RimeContext &context) { auto candidate = JRef<>(env, env->NewObject(GlobalRef->CandidateProto, GlobalRef->CandidateProtoInit, *JString(env, item.text), - *JString(env, item.comment))); + *JString(env, item.comment), + *JString(env, label))); env->SetObjectArrayElement(destCandidates, i, candidate); } menu = env->NewObject(GlobalRef->MenuProto, GlobalRef->MenuProtoInit, src.page_size, src.page_no, src.is_last_page, - src.highlighted_candidate_index, *destCandidates); + src.highlighted_candidate_index, *destCandidates, + *JString(env, src.select_keys), *destSelectLabels); } return env->NewObject(GlobalRef->ContextProto, GlobalRef->ContextProtoInit, *JRef<>(env, composition), *JRef<>(env, menu), - *JString(env, context.commit_text_preview), - *JRef<>(env, destSelectLabels)); + *JString(env, input.data()), caretPos); } inline jobject rimeStatusToJObject(JNIEnv *env, const RimeStatus &status) { diff --git a/app/src/main/jni/librime_jni/rime_jni.cc b/app/src/main/jni/librime_jni/rime_jni.cc index c4769f6cc1..5e54659d9f 100644 --- a/app/src/main/jni/librime_jni/rime_jni.cc +++ b/app/src/main/jni/librime_jni/rime_jni.cc @@ -285,9 +285,12 @@ Java_com_osfans_trime_core_Rime_getRimeContext(JNIEnv *env, jclass /* thiz */) { } RIME_STRUCT(RimeContext, context) auto rime = rime_get_api(); + auto session = Rime::Instance().sessionId(); jobject obj = nullptr; - if (rime->get_context(Rime::Instance().sessionId(), &context)) { - obj = rimeContextToJObject(env, context); + if (rime->get_context(session, &context)) { + std::string_view input(rime->get_input(session)); + int caretPos = static_cast(rime->get_caret_pos(session)); + obj = rimeContextToJObject(env, context, input, caretPos); rime->free_context(&context); } return obj;