Skip to content

Chờ sự kiện surrounding text thay vì ngủ theo hằng số (mặc định tắt) — làm lại #477 trên dev hiện tại - #492

Draft
nguyenphivn wants to merge 1 commit into
LotusInputMethod:devfrom
nguyenphivn:pr/cho-su-kien-v2
Draft

nguyenphivn wants to merge 1 commit into
LotusInputMethod:devfrom
nguyenphivn:pr/cho-su-kien-v2

Conversation

@nguyenphivn

Copy link
Copy Markdown
Contributor

Đây là bản làm lại của #477 trên nền dev hiện tại.

#477 gồm hai commit, trong đó commit đầu là vá cho #476 — mà bạn đã tự vá rồi ở 939f01a, nên nó thành thừa. Mình mở PR mới thay vì đẩy đè lên nhánh cũ để lịch sử không bị viết lại. PR này còn đúng một commit, tách thẳng từ dev, và mặc định TẮT nên không đổi hành vi của ai cho tới khi bật công tắc.

Vẫn để 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.

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 InputContextSurroundingTextUpdated lại đi qua đúng cái vòng lặp đang bị sleep_for 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, 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ùng realtextLen, quá hạn thì giao như cũ. Phím người dùng gõ trong lúc chờ vẫn vào buffered_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ỳ:

Vòng Đo thấy gì Sửa gì
v1 Người nghe sự kiện sống qua lần thay chữ sau, bắt tin trễ của phím trước → giao sớm, 0/15 Đăng ký nghe đúng lúc bắn phím xoá, huỷ ngay sau đó
v4 Ở nhịp 20 ms, ảnh cũ tụt hai phím trông y hệt trạng thái đã xoá xong (đươợ) Ảnh giống hệt ảnh lúc bắn phím xoá thì không tính là xong
v6 Firefox tụt lại thì ảnh không đáng tin nữa Sau một lần quá hạn, bỏ kiểm ngay cho tới khi có tin khớp
v7 Konsole khai có surrounding text nhưng gửi ảnh RỖNG suốt (valid=1 len=0) — chờ chỉ tốn trọn hạn mỗi dấu Ảnh rỗng thì bỏ chờ, đi đường ngủ cũ
v7.1 Hạn 40 ms nổ ở 64 ms, hạn 200 nổ ở 243, tệ nhất 430 addTimeEvent accuracy 0 của sd-event = mặc định 250 ms; đặt 1 ms
v8+v9 Ở nhịp 5 ms, ảnh lúc bắn luôn chậm một phím nên trông như xong; nhưng tin tới 0 ms sau khi quá hạn lại là bộ đệm cũ bắt kịp (trươnờ) Dùng thời gian: chỉ tin sau ngưỡng 8 ms × số phím xoá (đúng ngưỡng của chế độ Slow, đã đo 60/60)
v10 16/27 lần quá hạn còn lại là tin "xong" tới TRƯỚC ngưỡng rồi app im luôn Đặt thêm một mốc đúng tại ngưỡng, khớp thì giao ngay
v11–v12 Thanh địa chỉ Edge đóng băng ảnh trong lúc xoá, không bao giờ khớp Phát hiện đóng băng thì bỏ chờ, ngủ theo hằng số của Slow, thăm dò lại mỗi 4 lần
v12c Hạ hạn 200 → 100 → 50 ms vẫn 60/60 hai lượt Chọn 50 ms; dưới 40 ms là thấp hơn ngưỡng an toàn của Slow nên dừng

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

Ô nhập Nhịp 50 ms Nhịp 5 ms Chữ hiện trễ (trung vị)
Firefox, 4 ô soạn 60/60 60/60 (cả nhịp ngẫu nhiên 5–120 ms) 25 ms
Kate, Konsole, Alacritty 15/15 mỗi app 15/15 mỗi app 6–8 ms
KDialog (Qt), Meld (GTK3), Electron 15/15 mỗi app 15/15 mỗi app 6–7 ms
Edge, 4 ô trong trang 60/60 30/30 6 ms
Edge thanh địa chỉ 15/15 14/15 27 ms

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 đặt WaitSurroundingEvent=True trong lotus.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


🤖 Generated with Claude Code

https://claude.ai/code/session_01TvNe693ge85eB4QPs6hpjV

🤖 Generated with Claude Code

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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant