feat(windows): disable pen tap / press-hold visual feedback

On pen-down the OS drew the "Windows Ink" tap ripple / press-and-hold ring
under the nib — ugly and laggy-looking while writing. Set the tablet input
service's MicrosoftTabletPenServiceProperty on both the top-level window and
the Flutter child (where WM_POINTER lands) with the disable flags
(PENTAPFEEDBACK, PRESSANDHOLD, PENBARRELFEEDBACK, TOUCHUIFORCEON/OFF, FLICKS)
so the pen draws instantly with no OS animation.

Native-only change (windows/runner/flutter_window.cpp); built by CI.
This commit is contained in:
2026-06-23 16:52:25 +08:00
parent eae4493954
commit 8908f42f76

View File

@@ -29,6 +29,32 @@ LRESULT CALLBACK FlutterChildSubclassProc(HWND hwnd, UINT message,
return DefSubclassProc(hwnd, message, wparam, lparam);
}
// Turn off the OS-drawn pen visual feedback (the "Windows Ink" tap ripple, the
// press-and-hold right-click ring, barrel feedback, and flicks) so the pen
// draws instantly with no ugly OS animation under the nib. The tablet input
// service reads these flags from a window property; set it on whichever window
// receives the pointer input. Flag values are from the Windows pen/tablet docs
// (not declared in the public SDK headers).
void DisablePenVisualFeedback(HWND hwnd) {
if (!hwnd) {
return;
}
constexpr ULONG_PTR kDisablePressAndHold = 0x00000001;
constexpr ULONG_PTR kDisablePenTapFeedback = 0x00000008;
constexpr ULONG_PTR kDisablePenBarrelFeedback = 0x00000010;
constexpr ULONG_PTR kDisableTouchUIForceOn = 0x00000100;
constexpr ULONG_PTR kDisableTouchUIForceOff = 0x00000200;
constexpr ULONG_PTR kDisableFlicks = 0x00010000;
const ULONG_PTR flags = kDisablePressAndHold | kDisablePenTapFeedback |
kDisablePenBarrelFeedback | kDisableTouchUIForceOn |
kDisableTouchUIForceOff | kDisableFlicks;
const ATOM atom = ::GlobalAddAtomW(L"MicrosoftTabletPenServiceProperty");
if (atom != 0) {
::SetPropW(hwnd, MAKEINTATOM(atom), reinterpret_cast<HANDLE>(flags));
::GlobalDeleteAtom(atom);
}
}
} // namespace
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
@@ -64,6 +90,11 @@ bool FlutterWindow::OnCreate() {
SetWindowSubclass(flutter_child, FlutterChildSubclassProc, kPenSubclassId, 0);
}
// Kill the OS pen tap/press-and-hold visual feedback on both the top-level
// window and the Flutter child (the one that actually gets the pointer input).
DisablePenVisualFeedback(GetHandle());
DisablePenVisualFeedback(flutter_child);
flutter_controller_->engine()->SetNextFrameCallback([&]() {
this->Show();
});