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
{{ message }}
Repository navigation
После переключения раскладки клавишей Globe (🌐) нажатия теряются до клика мышью #15
После переключения раскладки клавишей Globe (🌐) все следующие нажатия выпадают из буфера слова, пока не кликнешь мышью. В режиме хоткея хоткей срабатывает с пустым буфером, и ничего не исправляется. В зависимости от тайминга иногда теряется только первая буква: ghbdtn → gпривет, fylhtq → fндрей.
В Electron-приложениях (например, десктопный Claude) воспроизводится каждый раз, в нативных (Sublime Text) — через раз.
keyDown клавиши Globe (keyCode 179) классифицируется как .navigation, а она invalidatesFocus. Контекст получает secureFocus = .unknown с эпохой E, и через 25 мс запланирован запрос фокуса для E (focusMayChange).
Примерно через 15 мс срабатывает selectedInputSourceChanged. Для не-сгенерированной смены он вызывает replaceContext(..., secureFocus: current.secureFocus): эпоха становится E+1, а статус остаётся .unknown.
Отложенный запрос возвращается для эпохи E, и CaptureStateStore.resolveFocus отбрасывает его из-за несовпадения эпохи. Для E+1 повторного запроса никто не делает, поэтому canBuffer остаётся false и каждый символ инвалидируется.
Debug-лог: нажатие Globe, затем набор, и focus resolved нет до клика:
(Последняя строка — из локального диагностического лога, добавленного в requestManualCorrection.)
Исправление
После ручной смены раскладки перезапрашивать фокус для новой эпохи, так же как это уже делает ветка сгенерированного переключения:
} else {
inputEngine?.handleLayoutChange(
from: oldLayout,
to: newLayout,
context: context,
fromVariant: fromVariant,
toVariant: toVariant
)
+ // The switch key (e.g. Globe) is captured as navigation and leaves focus+ // unknown; the new epoch orphans that pending query, so re-resolve here —+ // otherwise every keystroke is dropped until the next click.+ if context.secureFocus != .notSecure {+ focusCoordinator?.focusMayChange(pid: context.frontmostPID, epoch: context.epoch)+ }
}
Проверено локально: после правки Globe → ghbdtn → хоткей даёт привет и в десктопном Claude, и в Sublime Text.
Pre-merge audit against released v0.0.11 and PR #22 (commit 68873cc): still unresolved. No verified fixed version yet.
In AppDelegate.selectedInputSourceChanged(), a manual layout change creates a new context epoch while preserving the previous secure-focus state. Only the generated-selection branch schedules a fresh focus query. The reported stale-epoch/unknown-focus path therefore remains possible.
Proposed fix:
After handling a manual layout change, request focus resolution for the new PID/epoch whenever the inherited focus state is not .notSecure.
Add a regression check for navigation → unknown focus at epoch E → manual source change to E+1 → stale E result discarded → fresh E+1 result restores buffering. Retain fail-closed behavior for secure focus.
Verify Globe → type → correction in both a native editor and an Electron app, including rapid repeated switches.
Leaving open until this path is fixed and verified.
Activity
Hantok commentedon Oct 20, 2026
Pre-merge audit against released v0.0.11 and PR #22 (commit 68873cc): still unresolved. No verified fixed version yet.
In
AppDelegate.selectedInputSourceChanged(), a manual layout change creates a new context epoch while preserving the previous secure-focus state. Only the generated-selection branch schedules a fresh focus query. The reported stale-epoch/unknown-focus path therefore remains possible.Proposed fix:
.notSecure.Leaving open until this path is fixed and verified.