Conversation
shiena
force-pushed
the
ime-improvements
branch
3 times, most recently
from
April 26, 2026 14:27
96559f5 to
8b619ac
Compare
shiena
force-pushed
the
ime-improvements
branch
13 times, most recently
from
May 4, 2026 03:02
6448121 to
455eacb
Compare
This was referenced Aug 9, 2026
shiena
force-pushed
the
ime-improvements
branch
from
August 27, 2026 16:09
2092d36 to
512fe13
Compare
shiena
force-pushed
the
ime-improvements
branch
from
September 8, 2026 19:45
512fe13 to
8736ffc
Compare
Contributor
Author
|
Rebased onto #1849. Two commits are gone as a result:
|
…s live Under sustained IME key-repeat (corvus-skk hiragana holding a vowel) each tick floods the message queue with WM_KEYDOWN + the three WM_IME_* messages + a TerminalDamaged user event. The drain loop never sees an empty queue, so `about_to_wait` — which is the only site that calls `scheduler.update()` — never fires. The render scheduler timer therefore never expires, and even if it did, its RedrawRequested would still depend on WM_PAINT, the lowest-priority slot in a Win32 message queue and also starved by the same flood. Net effect: every `あ` is pasted to the PTY and echoed by the shell while held, but the screen only repaints when the key is released and the queue finally drains. Register a custom `REDRAW_REQUESTED_MSG` via `RegisterWindowMessageA` and post it from `Window::request_redraw`. Regular posted messages are returned by `PeekMessageW` ahead of the synthesized WM_PAINT, so the paint trigger interleaves with the IME flood. On the application side, `RioEvent::TerminalDamaged` skips the scheduler timer and calls `request_redraw` directly — vblank-rate pacing still belongs to the DwmFlush VSync worker via the dirty flag, so we aren't burning frames.
The previous commit's `Window::request_redraw` both posts `REDRAW_REQUESTED_MSG` *and* raises the DwmFlush worker's dirty flag, so each paint request caused two `RedrawRequested` dispatches per vblank: one via the custom message, one via the worker's `RedrawWindow(RDW_INVALIDATE)` -> `WM_PAINT` path. The second one is a no-op inside per-context render (the dirty flag was already cleared by the first pass) but still burns a frame of `begin_render` / `pre_present_notify` / present work. Clear the worker's dirty flag from the `REDRAW_REQUESTED_MSG` handler so the next tick sees it false and skips the redundant invalidate. Also drop the `present_after_input` fallback (and the `last_input_timestamp` / `mark_input_received` plumbing that fed it) since rio already drives redraws explicitly via `request_redraw` on every event that can mutate the terminal — the fallback was driving another 60 fps stream of invalidations during any input window, stacking on top of the custom-message paints.
…handshake
Tracing the WndProc for a held 'a' in corvus-skk hiragana
direct-input showed a very sharp pattern: WM_IME_STARTCOMPOSITION
was delivered immediately after WM_KEYDOWN, but the paired
WM_IME_COMPOSITION only arrived ~95–100 ms later, with the main
thread completely idle in between. The OS auto-repeat (~30 Hz)
kept queuing WM_KEYDOWN messages with accumulating repeat counts
(lparam low word 2, 4, …) while we were stuck waiting, so the
user only saw ~10 cps. Forwarding the IME messages to
`DefWindowProc` runs a synchronous handshake with the TIP — that
handshake is the 100 ms wait.
Return 0 for both START and ENDCOMPOSITION the way wezterm does
for ENDCOMPOSITION. The composition result still arrives via
`WM_IME_COMPOSITION`, just without the handshake stall, and the
per-keystroke cycle drops to ~31 ms — matching the OS auto-repeat
cadence (confirmed on a corvus-skk hiragana trace: 21.502086 s
START → 21.502169 s COMPOSITION, i.e. 0.08 ms vs. the prior
~98 ms).
Drop the `Ime::Enabled` / `Ime::Disabled` dispatches that START /
END used to send: the app's handler only toggled an unread
`enabled` flag, so for IMEs that fire this whole trio every
keystroke we were paying one full event-handler round-trip per
press for nothing.
The pre-commit `Ime::Preedit("")` in the GCS_RESULTSTR branch is
intentionally kept: most IMEs (MS-IME, Google Japanese Input,
ATOK) fire WM_IME_COMPOSITION on confirm with only GCS_RESULTSTR
— no GCS_COMPSTR — so the GCS_COMPSTR branch below never runs and
the app's `ime.preedit` would otherwise stay `Some(...)` from the
last preedit update. `process_key_event` short-circuits while a
preedit is active, so without this clear every keystroke after a
commit is silently dropped. For direct-input IMEs (corvus-skk
hiragana) that never had a preedit, the app's handler skips
damage/redraw because `None != None` is false — the extra event
is one no-op handler call, paid only on commit (not auto-repeat).
shiena
force-pushed
the
ime-improvements
branch
from
September 19, 2026 10:34
8736ffc to
d6bc97a
Compare
This branch has not been deployed
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.
grid_emit.rs, so Fix IME preedit overlay and add tests #1434's per-cellcreate_stylepatch no longer applies. Re-implemented against the new path:PreeditOverlayis threaded throughbuild_row_bg/build_row_fg, composition cells render as a wezterm-style block (cursor color bg, glyph inverted),Spacers skip emission so wide CJK chars stay contiguous, and the IME caret is a new
DecorationStyle::ImeCaretsprite.Co-Authored-By Tryanks.
WM_KEYDOWN+WM_IME_*TerminalDamaged, starvingabout_to_waitso the scheduler never fires a paint. Added a customREDRAW_REQUESTED_MSGposted by
Window::request_redraw— posted messages return fromPeekMessageWahead ofWM_PAINT, so paints interleavewith the flood. The handler clears the DwmFlush worker's dirty flag to avoid double-painting.
WM_IME_STARTCOMPOSITION/ENDCOMPOSITIONwere forwarded toDefWindowProc,which runs a ~100 ms synchronous TIP handshake — capping corvus-skk direct-input at ~10 cps. Returning 0 (wezterm already
does this for END) drops the per-keystroke cycle to ~31 ms, matching the OS repeat rate.