Repository navigation
Conversation
|
Xác nhận bản vá hoạt động, kèm bằng chứng cho phần "What I did not verify" Mình đã tái hiện được đúng khoảnh khắc macOS tắt event tap mà tác giả PR nói chưa bắt được, và xác nhận tap tự bật lại. Môi trường: macOS 26.6.2, Apple Silicon, build arm64. Cách build: vì Thay đổi nhỏ so với PR: mình đổi Cách ép lỗi xảy ra: trong một bản build riêng chỉ dùng để thử, mình chèn Kết quả (log, mốc thời gian tương đối):
Ngay sau đó, Lưu ý: mình mới chạy bản vá trong thời gian ngắn nên chưa kết luận được gì về độ ổn định dài hạn. Phần được xác nhận ở đây là cơ chế: notification có tới, và tap bật lại được. |
initEventTap creates an active event tap, so macOS puts a deadline on OpenKeyCallback. When the callback misses that deadline (sustained CPU load) or on kCGEventTapDisabledByUserInput, the system switches the tap off and reports it back through the callback as a pseudo event type. OpenKeyCallback never checked for those two types, and CGEventTapEnable was only ever called once during setup. Once macOS turned the tap off, nothing turned it back on: the menu bar still showed the current mode and the switch key still worked, but no keystroke was converted in any app until OpenKey was relaunched. Handle both notifications in the callback and re-enable the tap. The normal event path is unchanged. Refs tuyenvm#258
5a5e5fd to
21b98e3
Compare
|
Cảm ơn bạn đã test và gửi log chi tiết. Phía mình chưa ép được lỗi xảy ra nên phần xác minh còn thiếu. Log của bạn bổ sung đúng chỗ đó: macOS gửi Về việc ghi Đồng ý là cần dùng thêm một thời gian mới nói được về độ ổn định. Nếu có gì bất thường thì mình cùng xem tiếp nhé. |
Adapt upstream PRs tuyenvm#324, tuyenvm#329, tuyenvm#332 and tuyenvm#333. Preserve saved shortcuts, bound Spotlight focus queries, avoid reusing backspace events, and send complete UTF-16 chunks. Cover event processing and tap lifecycle under sanitizers.
The problem I ran into
I use OpenKey every day for Vietnamese typing on macOS, alongside Docker Desktop for work.
Every time I opened or restarted Docker Desktop, Vietnamese typing stopped working — in every app, not just Docker. OpenKey still looked fine: the menu bar icon still showed "V", and the switch key still toggled between V and E. But whatever I typed came out as plain keys, as if OpenKey was not there.
asstayedasinstead of becomingá.The only way back was to quit OpenKey and open it again. Then it happened again the next time Docker Desktop restarted.
Restarting Docker Desktop boots a VM and restarts containers, which keeps the CPU busy for a while. That turned out to be the trigger. Docker is not doing anything to OpenKey directly — it just makes the machine slow enough to expose the bug below.
This is the same symptom as #258 ("Tất cả các ứng dụng đều không gõ được VI ... khắc phục: reboot lại OS và bật lại OpenKey").
Root cause
initEventTapcreates an active event tap:macOS puts a deadline on an active tap's callback. If
OpenKeyCallbackdoes not return in time — which happens when the machine is under sustained load — the system switches the tap off and reports it back through the same callback as the pseudo event typekCGEventTapDisabledByTimeout.kCGEventTapDisabledByUserInputis the other case.Two things then go wrong on
master:OpenKeyCallbacknever checkstypeagainst those two values, so the notification is ignored.CGEventTapEnableis called exactly once, at the end ofinitEventTap.So once macOS turns the tap off, nothing ever turns it back on. The rest of the app keeps running, which is why the menu bar and the switch key still respond and it looks like OpenKey is working.
Fix
Handle both notifications at the top of the callback and re-enable the tap.
eventTapis file-static inOpenKeyManager.m, so re-enabling goes through a small C function there, in the same style as the existing cross-fileexterndeclarations.The normal event path is untouched — the guard returns before any existing logic runs.
Testing
xcodebuild -project Sources/OpenKey/macOS/OpenKey.xcodeproj -scheme OpenKey -configuration Release→ BUILD SUCCEEDED (Xcode 26.1.1, macOS 26.3)nmon the built binary confirms the new path is present andCGEventTapEnablenow has two call sites instead of one.Note:
MACOSX_DEPLOYMENT_TARGETin the project is10.14, which no longer builds on current Xcode (SDK does not contain 'libarclite'). I built with an override; that is a pre-existing issue unrelated to this change and I have not touched the project file.Verification of the disable → re-enable path
I could not force the tap to be disabled on demand myself: it needs the callback to be mid-flight during a CPU stall, so it only happens while actually typing.
@scvbuild has since reproduced it directly in this comment by stalling
OpenKeyCallbackfor 3 seconds in a test-only build. macOS deliveredtype = 0xFFFFFFFE(kCGEventTapDisabledByTimeout), and with this patchCGGetEventTapList()reported OpenKey's tap asenabled=YESagain on the same process, without relaunching the app.Refs #258