Преглед изворни кода

fix: reset composing state before closing input connection on focus loss

When switching IME or terminal tabs on Windows, the TSF framework
could deadlock with Flutter's TextInput channel because composing
state was not cleaned up before the input connection was closed.

Changes:
- _onFocusChange: clear composing state before closing connection
- _closeInputConnectionIfNeeded: reset editing state and notify
  composing callback to ensure clean state
- updateEditingValue: use null-safe _connection?.setEditingState
  to prevent crash during rapid focus switching
yangcong пре 2 недеља
родитељ
комит
8104a172e2
1 измењених фајлова са 16 додато и 1 уклоњено
  1. 16 1
      lib/src/ui/custom_text_edit.dart

+ 16 - 1
lib/src/ui/custom_text_edit.dart

@@ -130,6 +130,16 @@ class CustomTextEditState extends State<CustomTextEdit> with TextInputClient {
   }
 
   void _onFocusChange() {
+    if (!widget.focusNode.hasFocus) {
+      // 失去焦点时,先清理 composing 状态,再关闭 input connection。
+      // 如果不先清理,Windows TSF 框架在收到 close 时可能因为
+      // composing 状态不一致而与 Flutter TextInput channel 死锁,
+      // 导致切换输入法或切换终端 tab 时整个 UI 卡死。
+      if (!_currentEditingState.composing.isCollapsed) {
+        _currentEditingState = _initEditingState.copyWith();
+        widget.onComposing(null);
+      }
+    }
     _openOrCloseInputConnectionIfNeeded();
   }
 
@@ -195,8 +205,12 @@ class CustomTextEditState extends State<CustomTextEdit> with TextInputClient {
 
   void _closeInputConnectionIfNeeded() {
     if (_connection != null && _connection!.attached) {
+      // 关闭前重置 editing state,确保 IME 引擎收到一致的状态
+      _currentEditingState = _initEditingState.copyWith();
       _connection!.close();
       _connection = null;
+      // 通知外部清除 composing 文本显示
+      widget.onComposing(null);
     }
   }
 
@@ -249,7 +263,8 @@ class CustomTextEditState extends State<CustomTextEdit> with TextInputClient {
     // Reset editing state if composing is done
     if (_currentEditingState.composing.isCollapsed &&
         _currentEditingState.text != _initEditingState.text) {
-      _connection!.setEditingState(_initEditingState);
+      // 使用 null-check 防止快速切换焦点时 _connection 已被关闭
+      _connection?.setEditingState(_initEditingState);
     }
   }