Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug Fix 20250203 #1574

Merged
merged 5 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/com/osfans/trime/data/prefs/AppPrefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class AppPrefs(
const val POPUP_KEY_PRESS_ENABLED = "keyboard__show_key_popup"
const val SHOW_SCHEMA_SWITCHES = "show_schema_switches_in_idle"
const val SHOW_ARROW_IN_SWITCHES = "show_arrow_in_switches"
const val SWITCHES_DEBOUNCE_INTERVAL = "schema_switches_debounce_interval"
const val HIDE_QUICK_BAR = "hide_quick_bar"
const val LANDSCAPE_MODE = "keyboard__landscape_mode"
const val SPLIT_SPACE_PERCENT = "keyboard__split_space"
Expand Down Expand Up @@ -162,6 +163,7 @@ class AppPrefs(
val popupKeyPressEnabled = bool(POPUP_KEY_PRESS_ENABLED, false)
val showSchemaSwitches = bool(SHOW_SCHEMA_SWITCHES, true)
val showArrowInSwitches = bool(SHOW_ARROW_IN_SWITCHES, true)
val switchesDebounceInterval = int(SWITCHES_DEBOUNCE_INTERVAL, 300)
val hideQuickBar = bool(HIDE_QUICK_BAR, false)

enum class LandscapeModeOption {
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/com/osfans/trime/ime/bar/QuickBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class QuickBar(
private val prefs = AppPrefs.defaultInstance()

private val showSwitches by prefs.keyboard.showSchemaSwitches
private val debounceInterval by prefs.keyboard.switchesDebounceInterval
private val hideQuickBar by prefs.keyboard.hideQuickBar

val themedHeight =
Expand All @@ -73,7 +74,7 @@ class QuickBar(
AlwaysUi(context, theme).apply {
switchesUi.apply {
setSwitches(SchemaManager.visibleSwitches)
setOnSwitchClick { switch ->
setOnSwitchClick({ switch ->
val prevEnabled = switch.enabled
switch.enabled =
if (switch.options.isEmpty()) {
Expand All @@ -91,7 +92,7 @@ class QuickBar(
}
}
}
}
}, debounceTime = debounceInterval.toLong())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ class SwitchesUi(
switchesAdapter.submitList(list)
}

fun setOnSwitchClick(listener: (Schema.Switch) -> Unit) {
switchesAdapter.setOnDebouncedItemClick { adapter, _, position ->
val typed = (adapter as SwitchesAdapter)
if (typed.items.isEmpty()) return@setOnDebouncedItemClick
val switch = typed.items[position]
listener(switch)
fun setOnSwitchClick(
listener: (Schema.Switch) -> Unit,
debounceTime: Long = 300L,
) {
switchesAdapter.setOnDebouncedItemClick(debounceTime) { adapter, _, position ->
(adapter as? SwitchesAdapter)?.items?.getOrNull(position)?.let(listener)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class InputBroadcaster : InputBroadcastReceiver {

fun <T> addReceiver(receiver: T) {
if (receiver is InputBroadcastReceiver && receiver !is InputBroadcaster) {
receivers.add(receiver)
if (!receivers.contains(receiver)) {
receivers.add(receiver)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,43 +279,40 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
is RimeMessage.KeyMessage ->
it.data.let event@{
val keyCode = it.value.keyCode
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
val eventTime = SystemClock.uptimeMillis()
if (it.modifiers.release) {
sendUpKeyEvent(eventTime, keyCode, it.modifiers.metaState)
} else {
// TODO: look for better workaround for this
if (keyCode == KeyEvent.KEYCODE_ENTER) {
handleReturnKey()
return
}

if (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_EQUALS) {
// ignore KP_X keys, which is handled in `CommonKeyboardActionListener`.
// Requires this empty body becoz Kotlin request it
return
if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
when {
!it.modifiers.release && it.value.value > 0 -> {
runCatching {
commitText("${it.value.value.toChar()}")
}
}
else -> Timber.w("Unhandled Rime KeyEvent: $it")
}
return
}

it.modifiers.apply {
if (this.shift) sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)

sendDownKeyEvent(eventTime, keyCode, it.modifiers.metaState)
val eventTime = SystemClock.uptimeMillis()
if (it.modifiers.release) {
sendUpKeyEvent(eventTime, keyCode, it.modifiers.metaState)
return
}

if (this.shift) sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
// TODO: look for better workaround for this
if (keyCode == KeyEvent.KEYCODE_ENTER) {
handleReturnKey()
return
}

if (ctrl && keyCode == KeyEvent.KEYCODE_C) cancelTextSelection()
}
}
} else {
if (!it.modifiers.release && it.value.value > 0) {
try {
commitText(Char(it.value.value).toString())
} catch (_: Exception) {
}
} else {
Timber.w("Unhandled Rime KeyEvent: $it")
}
if (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_EQUALS) {
// ignore KP_X keys, which is handled in `CommonKeyboardActionListener`.
// Requires this empty body becoz Kotlin request it
return
}

if (it.modifiers.shift) sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
sendDownKeyEvent(eventTime, keyCode, it.modifiers.metaState)
if (it.modifiers.shift) sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
if (it.modifiers.ctrl && keyCode == KeyEvent.KEYCODE_C) clearTextSelection()
}
else -> {}
}
Expand Down Expand Up @@ -993,7 +990,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
if (et.selectionStart != et.selectionEnd) {
ic.performContextMenuAction(android.R.id.copy).also { result ->
if (result) {
cancelTextSelection()
clearTextSelection()
}
return result
}
Expand Down Expand Up @@ -1052,7 +1049,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
return false
}

fun cancelTextSelection() {
fun clearTextSelection() {
val ic = currentInputConnection ?: return
val etr = ExtractedTextRequest().apply { token = 0 }
val et = currentInputConnection.getExtractedText(etr, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ class CommonKeyboardActionListener(
}

override fun onAction(action: KeyAction) {
if (action.commit.isNotEmpty()) {
service.commitText(action.commit, true)
return
}
KeyboardSwitcher.currentKeyboard?.let {
if (action.getText(it).isNotEmpty()) {
onText(action.getText(it))
return
}
}
when (action.code) {
KeyEvent.KEYCODE_SWITCH_CHARSET -> { // Switch status
rime.launchOnReady { api ->
Expand Down Expand Up @@ -322,32 +332,30 @@ class CommonKeyboardActionListener(

override fun onText(text: CharSequence) {
if (!text.first().isAsciiPrintable() && Rime.isComposing) {
service.postRimeJob {
commitComposition()
}
service.postRimeJob { commitComposition() }
}

var sequence = text
while (sequence.isNotEmpty()) {
var slice: String
when {
BRACED_KEY_EVENT_WITH_ESCAPE.matches(sequence) -> {
slice = BRACED_KEY_EVENT_WITH_ESCAPE.matchEntire(sequence)?.groupValues?.get(1) ?: ""
// FIXME: rime will not handle the key sequence when
// ascii_mode is on, there may be a better solution
// for this.
if ((!Rime.simulateKeySequence(slice) || Rime.isAsciiMode) && !Rime.isComposing) {
service.commitText(slice)
}
val slice =
when {
BRACED_KEY_EVENT_WITH_ESCAPE.matches(sequence) ->
BRACED_KEY_EVENT_WITH_ESCAPE.matchEntire(sequence)?.groupValues?.get(1)
?: ""
BRACED_KEY_EVENT.matches(sequence) -> BRACED_KEY_EVENT.matchEntire(sequence)?.groupValues?.get(1) ?: ""
else -> sequence.first().toString()
}
BRACED_KEY_EVENT.matches(sequence) -> {
slice = BRACED_KEY_EVENT.matchEntire(sequence)?.groupValues?.get(1) ?: ""
onAction(KeyActionManager.getAction(slice))
}
else -> {
slice = sequence.first().toString()

service.postRimeJob {
if (slice.startsWith("{") && slice.endsWith("}")) {
onAction(KeyActionManager.getAction(slice))
} else {
if ((!Rime.simulateKeySequence(slice) || Rime.isAsciiMode) && !Rime.isComposing) {
service.commitText(slice.replace("{Escape}", ""))
}
}
}

sequence = sequence.substring(slice.length)
}
shouldReleaseKey = false
Expand Down
20 changes: 5 additions & 15 deletions app/src/main/java/com/osfans/trime/ime/keyboard/KeyboardView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ class KeyboardView(
}
if (sendDownKey) {
Timber.d("initGestureDetector: sendDownKey")
showPreview(NOT_A_KEY)
showPreview(mDownKey, behavior)
detectAndSendKey(mDownKey, mStartX, mStartY, me1.eventTime, behavior)
return true
Expand Down Expand Up @@ -738,23 +737,15 @@ class KeyboardView(
// Release the old key and press the new key
val keys = mKeys
if (oldKeyIndex != mCurrentKeyIndex) {
if (oldKeyIndex in keys.indices) {
val oldKey = keys[oldKeyIndex]
keys.getOrNull(oldKeyIndex)?.let { oldKey ->
oldKey.onReleased()
invalidateKey(oldKey)
if (showPreview) dismissKeyPreview(oldKey)
}
if (mCurrentKeyIndex in keys.indices) {
val newKey = keys[mCurrentKeyIndex]
keys.getOrNull(mCurrentKeyIndex)?.let { newKey ->
newKey.onPressed()
invalidateKey(newKey)
}
}
// If key changed and preview is on ...
if (oldKeyIndex != mCurrentKeyIndex && showPreview) {
if (keyIndex == NOT_A_KEY) {
dismissKeyPreview(keys[oldKeyIndex])
} else {
showKeyPreview(keys[keyIndex], behavior)
if (showPreview) showKeyPreview(newKey, behavior)
}
}
}
Expand Down Expand Up @@ -792,13 +783,12 @@ class KeyboardView(
if (mCurrentKey !in mKeys.indices) {
return false
}
showPreview(NOT_A_KEY)
showPreview(mCurrentKey, KeyBehavior.LONG_CLICK)
val popupKey = mKeys[mCurrentKey]
return onLongPress(popupKey).also {
if (it) {
mAbortKey = true
showPreview(-1)
showPreview(NOT_A_KEY)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class KeyboardWindow(
private val currentKeyboard: Keyboard? get() = cachedKeyboards[currentKeyboardId]?.first
private val currentKeyboardView: KeyboardView? get() = cachedKeyboards[currentKeyboardId]?.second

private val keyboardActionListener = ListenerDecorator(commonKeyboardActionListener.listener)
private val keyboardActionListener = commonKeyboardActionListener.listener

override fun onCreateView(): View {
keyboardView = context.frameLayout(R.id.keyboard_view)
Expand Down Expand Up @@ -313,25 +313,4 @@ class KeyboardWindow(
it.keyboardActionListener = null
}
}

inner class ListenerDecorator(
private val delegate: KeyboardActionListener,
) : KeyboardActionListener by delegate {
override fun onAction(action: KeyAction) {
if (action.commit.isNotEmpty()) {
// Directly commit the text and don't dispatch to Rime
service.commitText(action.commit, true)
return
}

currentKeyboard?.let {
if (action.getText(it).isNotEmpty()) {
onText(action.getText(it))
return
}
}

delegate.onAction(action)
}
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,5 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="deploy_failure">部署失败</string>
<string name="view_deploy_failure_log">部署失败。点此查看错误日志。</string>
<string name="hide_quick_bar">隐藏快捷栏</string>
<string name="schema_switches_debounce_interval">方案开关连击间隔</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,5 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="deploy_failure">部署失敗</string>
<string name="view_deploy_failure_log">部署失敗。點此檢視錯誤日誌。</string>
<string name="hide_quick_bar">隱藏快捷欄</string>
<string name="schema_switches_debounce_interval">方案開關連擊間隔</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,5 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="deploy_failure">Deploy failure</string>
<string name="view_deploy_failure_log">Deploy failure. Click here to view error log.</string>
<string name="hide_quick_bar">Hide quick bar</string>
<string name="schema_switches_debounce_interval">Schema switches debounce interval</string>
</resources>
12 changes: 12 additions & 0 deletions app/src/main/res/xml/keyboard_preference.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:title="@string/show_arrow_in_switches"
app:dependency="show_schema_switches_in_idle"
app:iconSpaceReserved="false" />
<com.osfans.trime.ui.components.DialogSeekBarPreference
android:defaultValue="300"
android:key="schema_switches_debounce_interval"
android:title="@string/schema_switches_debounce_interval"
app:allowDividerAbove="false"
app:dependency="show_schema_switches_in_idle"
app:iconSpaceReserved="false"
app:max="1000"
app:min="0"
app:seekBarIncrement="10"
app:unit="@string/unit__time_ms"
app:useSimpleSummaryProvider="true" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="hide_quick_bar"
Expand Down
Loading