Merge pull request #485 from fanlusky/fix/webview2-commit-render-sync

fix(server): WebView2 选词不再白等渲染同步超时
This commit is contained in:
Lu Fan(SonnyCalcr) authored and GitHub committed 2026-09-27 10:32:22 +08:00
commit b322b32321
4 files changed
+41 -2

No files matched your search

+5 -1
View File
@@ -12,6 +12,7 @@
#include <vector>
#include <windows.h>
#include "engine/core/word_item.h"
#include "ipc/candidate_render_sync.h"
#include "window/candidate_view_model.h"
namespace GlobalIme
@@ -256,7 +257,10 @@ inline void PublishRenderedCandidatePageGeneration(std::uint64_t generation)
{
{
std::lock_guard lock(candidate_render_mutex);
rendered_candidate_page_generation.store(generation, std::memory_order_release);
rendered_candidate_page_generation.store(
FanyImeIpc::AdvanceRenderedCandidateGeneration(
rendered_candidate_page_generation.load(std::memory_order_relaxed), generation),
std::memory_order_release);
}
candidate_render_cv.notify_all();
}
+9
View File
@@ -36,4 +36,13 @@ constexpr bool ShouldWaitForCandidateRender(std::uint64_t rendered, std::uint64_
}
return rendered < current;
}
// The render echo only moves forward. WebView2 echoes from async DOM callbacks, so a content-only
// update's callback can land after a dedup of the same content already echoed the newer generation;
// storing the older one left rendered one behind published and every selection waited out the full
// bound.
constexpr std::uint64_t AdvanceRenderedCandidateGeneration(std::uint64_t rendered, std::uint64_t echoed) noexcept
{
return echoed > rendered ? echoed : rendered;
}
} // namespace FanyImeIpc
+10 -1
View File
@@ -2492,7 +2492,16 @@ LRESULT CALLBACK WndProcCandWindow(HWND hwnd, UINT message, WPARAM wParam, LPARA
{
CAND_DIAG_LOGF(L"show folded into in-flight fine-tune caret=({},{})", Global::Point[0], Global::Point[1]);
CAND_DIAG_LOGF(L"candidate-frame path=folded-inflight content_gen={}", contentGeneration);
InflateCandWnd(str);
// The in-flight FineTune echoes only the page it captured, which may predate this one. Without
// an echo here a digit/space selection right after a fast burst waits out the full render-sync
// timeout, felt as a stall on commit.
InflateCandWnd(str, [contentGeneration, pageGeneration = candidatePage->generation]() {
if (!::is_global_wnd_cand_shown || contentGeneration != g_candidate_content_generation.load())
{
return;
}
Global::PublishRenderedCandidatePageGeneration(pageGeneration);
});
KillTimer(hwnd, TIMER_ID_CANDIDATE_MOVE_SETTLE);
SetTimer(hwnd, TIMER_ID_CANDIDATE_MOVE_SETTLE, kCandidateMoveSettleMs, nullptr);
return 0;
@@ -22,6 +22,23 @@ TEST_CASE(candidate_render_sync_waits_only_when_a_painted_page_lags_the_publishe
REQUIRE(!ShouldWaitForCandidateRender(8, 7, false, true));
}
TEST_CASE(candidate_render_echo_never_moves_backwards)
{
using FanyImeIpc::AdvanceRenderedCandidateGeneration;
using FanyImeIpc::ShouldWaitForCandidateRender;
// WebView2: a dedup echoes 332 synchronously, then the content-only DOM callback for the same
// content lands and echoes 331. The stale echo must not pull rendered back behind published.
std::uint64_t rendered = 330;
rendered = AdvanceRenderedCandidateGeneration(rendered, 332);
rendered = AdvanceRenderedCandidateGeneration(rendered, 331);
REQUIRE_EQ(rendered, 332u);
REQUIRE(!ShouldWaitForCandidateRender(rendered, 332, false, true));
// A newer echo still advances.
REQUIRE_EQ(AdvanceRenderedCandidateGeneration(332, 333), 333u);
}
TEST_CASE(candidate_render_sync_wait_is_bounded_to_a_visible_stall)
{
// The bound is a UX contract and a transport constraint: a wedged UI thread may delay a