Chờ sự kiện surrounding text thay vì ngủ theo hằng số (mặc định tắt), kèm vá luật theo app #476 - #477
Closed
nguyenphivn wants to merge 3 commits into
Closed
nguyenphivn wants to merge 3 commits into
nguyenphivn wants to merge 3 commits into
Conversation
`LotusState::setEngine()` ghi thẳng `realMode = config.mode` — mặc định CHUNG. Nhưng `setEngine()` chạy trong hàm dựng của MỌI `LotusState` và trong `refreshEngine()` cho MỌI input context, mà cả hai đều không biết cửa sổ nào đang gõ. Kết quả: một input context mới (ứng dụng khác vừa mở) hoặc một lần nạp lại cấu hình sẽ thổi bay luật riêng của cửa sổ đang hoạt động, cho tới lần đổi focus kế tiếp. Sửa: - `setEngine()` không còn ghi `realMode`. - `refreshEngine()` đặt lại chế độ theo đúng luật của app đang có focus qua `setMode(getAppRule(getProgramName(ic)), ic)`. `reloadConfig()` đã gọi `loadAppRules()` trước `populateConfig()` nên luật đọc ở đây là luật mới. - Không có cửa sổ nào đang gõ thì giữ mặc định chung như hành vi cũ; lần focus kế tiếp `activate()` đặt lại cho đúng. Sau thay đổi này `realMode` chỉ còn được ghi ở `setMode()`, tức mọi lần ghi đều đi qua tra luật theo app. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvNe693ge85eB4QPs6hpjV
…c định TẮT)
Chế độ uinput bắn phím xoá qua nhân rồi giao chữ mới qua Wayland. Hai đường khác
nhau nên chữ mới có thể vượt mặt phím xoá, gõ nhanh là mất chữ. Bản hiện tại chờ
bằng cách ngủ 2 ms mỗi phím xoá rồi thử lại 3 lần × 2 ms.
Chỗ ngủ đó không thể đúng được: fcitx5 chỉ có MỘT vòng lặp sự kiện, mà tin "ô nhập
đã đổi" (InputContextSurroundingTextUpdated) lại đi qua đúng vòng lặp đang bị chặn.
Ngủ bao lâu cũng không thấy tin tới; vòng thử lại 3 × 2 ms vì thế vô nghĩa về mặt
cấu trúc.
Thay bằng: trả vòng lặp về ngay, đăng ký nghe sự kiện đó, kiểm bằng NỘI DUNG ảnh ô
nhập, quá hạn thì giao như cũ. Phím người gõ trong lúc chờ vẫn vào buffered_keys_
như trước.
Bảy công tắc cấu hình, tất cả mặc định giữ nguyên hành vi cũ (WaitSurroundingEvent
mặc định false). Để nguyên để ai muốn đo lại có chỗ vặn:
WaitSurroundingEvent bật đường chờ sự kiện (mặc định false)
WaitSurroundingTimeoutMs hạn chờ, 50
WaitSurroundingShortMs hạn rút sau hai lần quá hạn liền, 40
WaitSurroundingProbeEvery app đóng băng ảnh thì thăm dò lại mỗi N lần, 4
WaitSurroundingMinPerKeyMs ngưỡng tin ảnh "trông như xong", 8 ms mỗi phím xoá
SurrDeleteSleepMs hằng số ngủ cũ của đường surrounding text, 4
SurrCommitSleepMs hằng số ngủ cũ sau khi giao chữ, 3
Số đo trên KDE Wayland (CachyOS), bàn phím ảo uinput, cùng một bản dựng, đối chứng
là tắt công tắc:
Firefox 4 ô soạn 60/60 ở nhịp 5 ms và ở nhịp ngẫu nhiên 5-120 ms
(bản hiện tại: 9-14/15)
Kate, Konsole, 15/15 mỗi app ở nhịp 50 ms và 5 ms
Alacritty, KDialog,
Meld, Electron
Edge 4 ô trang 60/60 ở nhịp 50 ms
Edge thanh địa chỉ 15/15 ở nhịp 50 ms; 14/15 ở nhịp 5 ms
(ca sai là lỗi Chromium LotusInputMethod#190, có ở cả bản hiện tại)
Chữ hiện trễ thêm: trung vị 6-8 ms ở app thường, 25 ms ở Firefox.
Đánh đổi đã đo được, xin khai thẳng: đường này giữ chữ đang treo qua một nhịp của
vòng lặp, nên nếu người dùng đổi cửa sổ trong vòng 50 ms sau khi bấm phím dấu thì
ô CŨ mất chữ đó. Đã thử vá bằng cách giao nốt lúc mất tiêu điểm — nhật ký ghi đúng
nhưng chữ vẫn không tới nơi, vì fcitx5 không giao được vào input context đang mất
tiêu điểm. Đường ngủ cũ không có khe này vì nó chặn vòng lặp. Chữ KHÔNG rơi sang
cửa sổ mới (đã đo), và cửa sổ mới vẫn gõ bình thường.
ctest 8/8 (bài smooth_buffered_key_replay cần chạy trong network namespace riêng
vì fcitx5-lotus-server đang giữ socket).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EahWp9MhUvHaPU2SpWPTLa
This was referenced Sep 11, 2026
Contributor
Author
|
Mình đóng PR này và mở lại ở #492. Lý do: commit đầu của nó là vá cho #476, mà bạn đã tự vá ở Nội dung mô tả và số đo giữ nguyên, mình chỉ bỏ phần đã trùng. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Chào bạn, mình gửi PR này ở dạng draft vì phần thử nghiệm còn 7 công tắc cấu hình để ai muốn cũng đo lại được — mình để bạn xem hướng trước rồi mới dọn.
PR có hai commit tách bạch:
fix: giữ luật theo app khi nạp lại cấu hình— chính là issue Luật theo app tụt về mặc định chung sau khi nạp lại cấu hình, không cần đổi cửa sổ #476 bạn đã xem.thử nghiệm: chờ sự kiện surrounding text thay vì ngủ theo hằng số— mặc định TẮT, không đổi hành vi của ai cho tới khi bật công tắc.Bạn muốn tách hẳn ra hai PR thì mình tách, commit 1 đứng độc lập được.
Vấn đề
Chế độ uinput bắn phím xoá qua nhân rồi giao chữ mới qua Wayland. Hai đường khác nhau nên chữ mới vượt mặt phím xoá, gõ nhanh là mất chữ. Bản hiện tại chờ bằng cách ngủ 2 ms mỗi phím xoá rồi thử lại 3 lần × 2 ms.
Chỗ ngủ đó không thể đúng được, và đây là chỗ mình mất nhiều thời gian nhất mới hiểu ra: fcitx5 chỉ có MỘT vòng lặp sự kiện, mà tin
InputContextSurroundingTextUpdatedlại đi qua đúng cái vòng lặp đang bịsleep_forchặn. Ngủ bao lâu cũng không thấy tin tới — vòng thử lại 3 × 2 ms vì thế vô nghĩa về mặt cấu trúc, không phải vì hằng số nhỏ quá.Chứng minh bằng đo: tăng hằng số ngủ lên gấp 12,5 lần trên đường surrounding text, Firefox đi từ 8/15 lên 9/15 — nằm trong nhiễu.
Cách chữa
Trả vòng lặp về ngay, đăng ký nghe
InputContextSurroundingTextUpdated, kiểm bằng nội dung ảnh ô nhập chứ không dùngrealtextLen, quá hạn thì giao như cũ. Phím người dùng gõ trong lúc chờ vẫn vàobuffered_keys_như trước.Cách đo
Bàn phím ảo uinput gõ 15 chuỗi tiếng Việt vào từng ô nhập thật, đọc lại nội dung ô rồi so với chuỗi mong đợi. Đối chứng luôn là cùng một bản dựng, tắt công tắc — không so giữa hai bản build khác nhau. Mỗi vòng khai trước con số dự đoán rồi mới chạy, đoán trật thì ghi lại.
Hành trình đo — mỗi vòng sửa vì đo thấy gì
Mình để nguyên phần này vì nó giải thích vì sao mã có mấy nhánh trông kỳ:
đươợ)valid=1 len=0) — chờ chỉ tốn trọn hạn mỗi dấuaddTimeEventaccuracy 0 của sd-event = mặc định 250 ms; đặt 1 mstrươnờ)Hai lần mình đoán sai và phải ghi lại: v11 dự đoán trung vị 15–20 ms, đo ra 46 ms vì ngủ chồng hai lần; và một lần kết luận nhầm rằng Electron trên X11 không nối được fcitx5 — thủ phạm thật là một hộp thoại của app che mất ô soạn, đã rút lại.
Số đo cuối
Bản hiện tại trên Firefox: 9–14/15.
Về #190 — lặp chữ đầu trên thanh địa chỉ Chromium
Mình dùng bản này hằng ngày trên KDE Wayland, chế độ Uinput (Smooth), và lỗi lặp chữ đầu ở thanh địa chỉ Chromium không còn xuất hiện nữa. Gõ ở những chỗ trước đây hay gợn — Facebook, Google Chat — giờ đều mượt.
Số đo cũng đi cùng hướng: thanh địa chỉ Edge 15/15 ở nhịp 50 ms, tức tốc độ gõ tay, không lặp lần nào.
Nói cho đủ: ở nhịp 5 ms — nhanh hơn người gõ nhiều lần, chỉ máy mới gõ được thế — bộ đo vẫn bắt được 2/15 ca lặp kiểu
dđược,dđồng hồ. Nên mình để đây như một báo cáo dùng thật, không dám khẳng định đã đóng được #190 trong mọi hoàn cảnh. Rất mong bạn và những người đang gặp #190 bật công tắc lên thử giúp — chỉ cần đặtWaitSurroundingEvent=Truetronglotus.conf, không cần đổi gì khác.Đánh đổi, mình khai thẳng
Đường này giữ chữ đang treo qua một nhịp của vòng lặp, nên nếu người dùng đổi cửa sổ trong vòng 50 ms sau khi bấm phím dấu thì ô CŨ mất chữ đó. Mình đã thử vá bằng cách giao nốt lúc mất tiêu điểm: nhật ký ghi đúng nhưng chữ vẫn không tới nơi, vì fcitx5 không giao được chuỗi vào input context đang mất tiêu điểm. Đường ngủ cũ không có khe này vì nó chặn vòng lặp.
Hai điều đã đo và yên tâm được: chữ không rơi sang cửa sổ mới, và cửa sổ mới vẫn gõ bình thường.
Hàng đợi
buffered_keys_(trần 50 phím) thì an toàn: với hạn 50 ms phải gõ hơn 1000 phím/giây mới tràn.Còn thiếu
ctesthiện tại 8/8 (bàismooth_buffered_key_replayphải chạy trong network namespace riêng vìfcitx5-lotus-serverđang giữ socket).🤖 Generated with Claude Code
https://claude.ai/code/session_01TvNe693ge85eB4QPs6hpjV