From c53afc3a8613f899bdd73a7431ffeafc736b637a Mon Sep 17 00:00:00 2001 From: Songbum Bae Date: Sun, 28 Jun 2026 10:27:56 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=B0=A9=ED=96=A5=ED=82=A4=20=EB=A1=B1?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=8A=A4=20=EC=97=B0=EC=86=8D=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A7=80=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 방향키(상/하/좌/우)를 RepeatKeyTouchListener로 교체해 꾹 누르면 연속 이동 - RepeatKeyTouchListener가 키를 람다(keyProvider)로 받도록 변경해 선택 모드(SELECT_ARROW_*) 대응 - 고정 키 기존 호출부 호환용 보조 생성자 추가 - @Volatile 및 Timer? 적용으로 타이머 누수와 스레드 가시성 문제 수정 - ArrowView.onDetachedFromWindow()에서 방향키·백스페이스 타이머 정리 --- .../openmoa/view/keyboardview/ArrowView.kt | 70 +++++++++++-------- .../RepeatKeyTouchListener.kt | 19 +++-- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/app/src/main/kotlin/pe/aioo/openmoa/view/keyboardview/ArrowView.kt b/app/src/main/kotlin/pe/aioo/openmoa/view/keyboardview/ArrowView.kt index 67d6b6a..c1825e9 100644 --- a/app/src/main/kotlin/pe/aioo/openmoa/view/keyboardview/ArrowView.kt +++ b/app/src/main/kotlin/pe/aioo/openmoa/view/keyboardview/ArrowView.kt @@ -32,6 +32,11 @@ class ArrowView : ConstraintLayout { private lateinit var binding: ArrowViewBinding private var isSelecting = false + private var upKeyListener: RepeatKeyTouchListener? = null + private var downKeyListener: RepeatKeyTouchListener? = null + private var leftKeyListener: RepeatKeyTouchListener? = null + private var rightKeyListener: RepeatKeyTouchListener? = null + private var backspaceKeyListener: RepeatKeyTouchListener? = null private fun init() { inflate(context, R.layout.arrow_view, this) @@ -64,13 +69,12 @@ class ArrowView : ConstraintLayout { copyKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.COPY)) ) - upKey.setOnTouchListener( - FunctionalKeyTouchListener(context) { - SpecialKeyMessage( - if (isSelecting) SpecialKey.SELECT_ARROW_UP else SpecialKey.ARROW_UP - ) - } - ) + upKeyListener = RepeatKeyTouchListener(context) { + SpecialKeyMessage( + if (isSelecting) SpecialKey.SELECT_ARROW_UP else SpecialKey.ARROW_UP + ) + } + upKey.setOnTouchListener(upKeyListener) cutKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.CUT)) ) @@ -87,26 +91,24 @@ class ArrowView : ConstraintLayout { selectAllKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.SELECT_ALL)) ) - leftKey.setOnTouchListener( - FunctionalKeyTouchListener(context) { - SpecialKeyMessage( - if (isSelecting) SpecialKey.SELECT_ARROW_LEFT else SpecialKey.ARROW_LEFT - ) - } - ) + leftKeyListener = RepeatKeyTouchListener(context) { + SpecialKeyMessage( + if (isSelecting) SpecialKey.SELECT_ARROW_LEFT else SpecialKey.ARROW_LEFT + ) + } + leftKey.setOnTouchListener(leftKeyListener) areaSelectKey.setOnTouchListener( FunctionalKeyTouchListener(context) { setSelectingOrToggleSelecting() null } ) - rightKey.setOnTouchListener( - FunctionalKeyTouchListener(context) { - SpecialKeyMessage( - if (isSelecting) SpecialKey.SELECT_ARROW_RIGHT else SpecialKey.ARROW_RIGHT - ) - } - ) + rightKeyListener = RepeatKeyTouchListener(context) { + SpecialKeyMessage( + if (isSelecting) SpecialKey.SELECT_ARROW_RIGHT else SpecialKey.ARROW_RIGHT + ) + } + rightKey.setOnTouchListener(rightKeyListener) endKey.setOnTouchListener( FunctionalKeyTouchListener(context) { SpecialKeyMessage( @@ -117,19 +119,18 @@ class ArrowView : ConstraintLayout { deleteKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.DELETE)) ) - downKey.setOnTouchListener( - FunctionalKeyTouchListener(context) { - SpecialKeyMessage( - if (isSelecting) SpecialKey.SELECT_ARROW_DOWN else SpecialKey.ARROW_DOWN - ) - } - ) + downKeyListener = RepeatKeyTouchListener(context) { + SpecialKeyMessage( + if (isSelecting) SpecialKey.SELECT_ARROW_DOWN else SpecialKey.ARROW_DOWN + ) + } + downKey.setOnTouchListener(downKeyListener) pasteKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.PASTE)) ) - backspaceKey.setOnTouchListener( + backspaceKeyListener = RepeatKeyTouchListener(context, SpecialKeyMessage(SpecialKey.BACKSPACE)) - ) + backspaceKey.setOnTouchListener(backspaceKeyListener) languageKey.setOnTouchListener( SimpleKeyTouchListener(context, SpecialKeyMessage(SpecialKey.LANGUAGE)) ) @@ -145,4 +146,13 @@ class ArrowView : ConstraintLayout { } } + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + upKeyListener?.endTimer() + downKeyListener?.endTimer() + leftKeyListener?.endTimer() + rightKeyListener?.endTimer() + backspaceKeyListener?.endTimer() + } + } \ No newline at end of file diff --git a/app/src/main/kotlin/pe/aioo/openmoa/view/keytouchlistener/RepeatKeyTouchListener.kt b/app/src/main/kotlin/pe/aioo/openmoa/view/keytouchlistener/RepeatKeyTouchListener.kt index a8943e3..6834c01 100644 --- a/app/src/main/kotlin/pe/aioo/openmoa/view/keytouchlistener/RepeatKeyTouchListener.kt +++ b/app/src/main/kotlin/pe/aioo/openmoa/view/keytouchlistener/RepeatKeyTouchListener.kt @@ -9,26 +9,31 @@ import java.util.Timer class RepeatKeyTouchListener( context: Context, - private val key: BaseKeyMessage, + private val keyProvider: () -> BaseKeyMessage?, ) : BaseKeyTouchListener(context) { + constructor(context: Context, key: BaseKeyMessage) : this(context, { key }) + + @Volatile private var elapsed = 0L - private lateinit var timer: Timer + private var timer: Timer? = null private fun startTimer() { + endTimer() elapsed = 0L - sendKeyMessage(key) + keyProvider()?.let { sendKeyMessage(it) } timer = kotlin.concurrent.timer(period = config.longPressRepeatTime) { elapsed += config.longPressRepeatTime if (elapsed >= config.longPressThresholdTime) { - sendKeyMessage(key) + keyProvider()?.let { sendKeyMessage(it) } } } } - private fun endTimer() { - timer.cancel() - elapsed = 0 + fun endTimer() { + timer?.cancel() + timer = null + elapsed = 0L } @SuppressLint("ClickableViewAccessibility")