Skip to content

[Windows] Window resize lags behind the pointer starting with nativeapi 0.2.5 #17

Closed

Description

@portlek

Description

Resizing a Flutter window on Windows becomes very slow and visibly lags behind the mouse pointer with nativeapi/cnativeapi 0.2.5. The same application resizes smoothly with 0.2.4.

Minimal reproduction

Reproduction project: https://github.com/Infumia/nativeapi_resize_lag

On Windows with Flutter 3.47 or newer, run the project with each version. Close the app between runs:

flutter pub add nativeapi:0.2.4 cnativeapi:0.2.4
flutter clean
flutter run -d windows --release --dart-define=NATIVEAPI_VERSION=0.2.4

Repeat with 0.2.5 in both commands, then continuously drag the right or bottom edge of the window back and forth.

Expected behavior

The window edge follows the pointer smoothly, as it does with 0.2.4.

Observed behavior

With 0.2.5, resizing stalls and the window follows the pointer with a substantial delay, moving in jumps. The regression is also observed in the original application with 0.2.7 and 0.3.0, in both debug and release builds.

Build log

flutter build windows --release

C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\menu_c.cpp(563,30): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\nativeapi\nativeapi.vcxproj]                                                                            
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\preferences_c.cpp(124,25): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\nativeapi\nativeapi.vcxproj]                                                                     
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\secure_storage_c.cpp(124,25): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\nativeapi\nativeapi.vcxproj]                                                                  
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\string_utils_c.cpp(11,10): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\nativeapi\nativeapi.vcxproj]                                                                                                                     
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\menu_c.cpp(563,30): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\cnativeapi.vcxproj]                                                                                     
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\preferences_c.cpp(124,25): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\cnativeapi.vcxproj]                                                                              
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\secure_storage_c.cpp(124,25): warning C4267: 'return': 'size_t' - 'unsigned long' dönüşümü; veri kaybı olabilir [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\cnativeapi.vcxproj]                                                                           
C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\windows\flutter\ephemeral\.plugin_symlinks\cnativeapi\cxx_impl\src\capi\string_utils_c.cpp(11,10): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. [C:\Users\hasan\Projects\datacorp_root\nativeapi_resize_lag\build\windows\x64\plugins\cnativeapi\shared\cnativeapi.vcxproj]                                                                                                                              
Building Windows application...                                    80,5s
√ Built build\windows\x64\runner\Release\nativeapi_resize_lag.exe

0.2.4 showcase

0.2.4.mp4

0.2.5 showcase

0.2.5.mp4

Activity

  1. lijy91 commented on Sep 25, 2026

    @lijy91
    Member

    Thanks for the detailed report and the reproduction project — it made this easy to pin down.

    Cause. 0.2.5 started emitting WindowMovedEvent / WindowResizedEvent (and minimized/maximized/restored) on Windows through a process-wide EVENT_OBJECT_LOCATIONCHANGE WinEvent hook. Out-of-context WinEvents are queued to the UI thread and delivered whenever it next reads a message — including inside Flutter's resize, which pumps messages while it waits for a frame of the new size. Every pointer move queued work there, and each window change called the (synchronous) Dart listener from the middle of that wait, so the window fell behind the pointer. 0.2.4 didn't emit these events at all, hence no lag.

    Fix (libnativeapi/nativeapi-core@e64ad99): the hook is gone. Each reported window is subclassed and the events are emitted from WM_WINDOWPOSCHANGED, after the window's own procedure — and so Flutter's resize — has finished. No API change.

    Verification on Windows 11 (150% scaling, Flutter 3.47.5, release build of your reproduction project), dragging the right edge back and forth with synthetic input while sampling cursor vs. window edge every ~1 ms:

    pointer rate before (p50 / p95 / max edge lag) after
    1000 Hz, run 1 32 / 140 / 170 ms 8 / 18 / 36 ms
    1000 Hz, run 2 10 / 39 / 74 ms 8 / 18 / 26 ms
    125 Hz 4 / 16 / 26 ms 3 / 16 / 30 ms

    WindowResizedEvent is still delivered on every step (the native and Flutter metrics counters in your app match).

    One behaviour note: window procedures can only be subclassed from the thread that owns the window, so windows created on a different thread than the one that first uses WindowManager no longer get moved/resized/minimized/maximized/restored events (created/closed still work). Flutter apps have all their windows on the platform thread, so they are not affected.

    The fix will ship in the next release. Until then you can try it by pointing dependency_overrides for nativeapi and cnativeapi at a checkout of this repository (bindings/dart/nativeapi, bindings/dart/cnativeapi). If you still see lag, please reopen with your mouse's polling rate and display scaling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions