You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fcitx5 chỉ có một event loop cho cả máy, nên trong lúc ngủ mọi cửa sổ đều đứng, không riêng ô đang gõ.
Vòng retry còn tệ hơn: nó chờ surroundingText() đổi, nhưng loop đang bị chặn nên giá trị đó không thể đổi giữa các lần thử. Điều kiện sai lần đầu thì cả 3 lần đều sai, và lần nào cũng mất trọn 6 ms. Với app không có surrounding text (Chromium trên X11, terminal) thì lần thay chữ nào cũng mất 6 ms này.
Mình đo bằng cách bọc keyEvent một đồng hồ, ghi thời gian mỗi lần nó giữ loop. Bàn phím ảo uinput, 15 cụm Telex, 50 ms/phím (tốc độ tay):
tổng thời gian loop bị chặn
lâu nhất
số phím chặn ≥ 5 ms
Thanh địa chỉ Edge
482 ms
12,4 ms
48
gnome-terminal (Super Smooth)
483 ms
12,5 ms
48
Ô GTK3
342 ms
10,5 ms
29
Các bước tái hiện
Mode = Uinput (Smooth)
Gõ tiếng Việt có dấu ở bất kỳ app nào
Mỗi lần Lotus thay chữ, fcitx5 đứng 2–14 ms
Kết quả mong đợi
Lotus chờ app xoá xong mà không chặn event loop.
Kết quả thực tế
sleep_for chặn cả fcitx5 mỗi lần thay chữ.
Hướng fix
Giữ nguyên khoảng chờ (sleepTime × (N − 1), cộng 6 ms nếu điều kiện retry sai), nhưng chờ bằng addTimeEvent rồi trả loop về ngay. Điều kiện retry quyết một lần lúc bắt đầu chờ, đúng như cái bản sleep_for thực chất đang làm.
Có ba chỗ phải xử lý kèm:
Phím tới trong lúc chờ (gõ rất nhanh): chờ nốt phần còn lại, commit, rồi xử lý phím đó như thường. Mình thử cách cất vào buffered_keys_ rồi replay bằng commitString thì Chromium X11 rơi chữ. Cách "chờ nốt" giữ đúng thứ tự như bản sleep_for, và chỉ chặn loop khi thật sự có phím chen vào.
Test headless (smooth_buffered_key_replay, held_key_repeat) đang ngầm giả định commit xảy ra ngay trong keyEvent. Mình thêm pumpEventLoop() vào test-input-context.h để chạy loop vài chục ms. EventLoop::exec() gọi lần hai sau exit() thì sd-event ném -ESTALE, nên mình phải gọi sd_event_run qua dlsym. Chỗ này bạn có cách gọn hơn thì mình đổi.
Sau fix, cùng cách đo:
tổng bị chặn
lâu nhất
số phím chặn ≥ 5 ms
Thanh địa chỉ Edge
34 ms
0,6 ms
0
gnome-terminal
30 ms
0,7 ms
0
Ô GTK3
38 ms
0,7 ms
0
Gõ đúng/sai không đổi ở 10, 15, 20, 50 ms/phím và khi gõ chồng phím 30 ms (Edge, Firefox, GTK3, gnome-terminal). Bấm Backspace ngay 1 ms sau phím dấu vẫn đúng (5/5). ctest 10/10.
Đánh đổi: ở 5 ms/phím (200 phím/giây, nhanh hơn tay người nhiều) thanh địa chỉ Edge còn 17/30, bản cũ 15/15. Nguyên nhân mình chưa tìm ra. Mới đo trên X11 (GNOME), chưa đo Wayland.
Code: commit 14d064d trên nhánh nguyenphivn:b33/hen-gio. Nhánh này hiện nằm trên nền #477 và fix của #486. Bạn thấy hướng ổn thì mình tách một nhánh riêng trên dev.
Mô tả lỗi
Mode Uinput (Smooth / Super Smooth / Slow), mỗi lần thay chữ (
e→ê, thêm dấu...) Lotussleep_forngay trongkeyEventtrước khi commit:src/lotus-state.cpp:449:sleep_for(sleepTime * (expected_backspaces_ - 1))src/lotus-state.cpp:457: retry 3 ×sleep_for(2 ms)fcitx5 chỉ có một event loop cho cả máy, nên trong lúc ngủ mọi cửa sổ đều đứng, không riêng ô đang gõ.
Vòng retry còn tệ hơn: nó chờ
surroundingText()đổi, nhưng loop đang bị chặn nên giá trị đó không thể đổi giữa các lần thử. Điều kiện sai lần đầu thì cả 3 lần đều sai, và lần nào cũng mất trọn 6 ms. Với app không có surrounding text (Chromium trên X11, terminal) thì lần thay chữ nào cũng mất 6 ms này.Mình đo bằng cách bọc
keyEventmột đồng hồ, ghi thời gian mỗi lần nó giữ loop. Bàn phím ảo uinput, 15 cụm Telex, 50 ms/phím (tốc độ tay):Các bước tái hiện
Kết quả mong đợi
Lotus chờ app xoá xong mà không chặn event loop.
Kết quả thực tế
sleep_forchặn cả fcitx5 mỗi lần thay chữ.Hướng fix
Giữ nguyên khoảng chờ (
sleepTime × (N − 1), cộng 6 ms nếu điều kiện retry sai), nhưng chờ bằngaddTimeEventrồi trả loop về ngay. Điều kiện retry quyết một lần lúc bắt đầu chờ, đúng như cái bảnsleep_forthực chất đang làm.Có ba chỗ phải xử lý kèm:
buffered_keys_rồi replay bằngcommitStringthì Chromium X11 rơi chữ. Cách "chờ nốt" giữ đúng thứ tự như bảnsleep_for, và chỉ chặn loop khi thật sự có phím chen vào.smooth_buffered_key_replay,held_key_repeat) đang ngầm giả định commit xảy ra ngay trongkeyEvent. Mình thêmpumpEventLoop()vàotest-input-context.hđể chạy loop vài chục ms.EventLoop::exec()gọi lần hai sauexit()thì sd-event ném-ESTALE, nên mình phải gọisd_event_runquadlsym. Chỗ này bạn có cách gọn hơn thì mình đổi.Sau fix, cùng cách đo:
Gõ đúng/sai không đổi ở 10, 15, 20, 50 ms/phím và khi gõ chồng phím 30 ms (Edge, Firefox, GTK3, gnome-terminal). Bấm Backspace ngay 1 ms sau phím dấu vẫn đúng (5/5). ctest 10/10.
Đánh đổi: ở 5 ms/phím (200 phím/giây, nhanh hơn tay người nhiều) thanh địa chỉ Edge còn 17/30, bản cũ 15/15. Nguyên nhân mình chưa tìm ra. Mới đo trên X11 (GNOME), chưa đo Wayland.
Code: commit
14d064dtrên nhánhnguyenphivn:b33/hen-gio. Nhánh này hiện nằm trên nền #477 và fix của #486. Bạn thấy hướng ổn thì mình tách một nhánh riêng trêndev.Phiên bản fcitx5-lotus
dev2fb0b82(code liên quan giống 3.5.9)Cách cài đặt
Tự build từ source
Hệ điều hành / Distro
Ubuntu 24.04
Môi trường Desktop
GNOME (X11)