diff --git a/flutter_inappwebview_windows/CHANGELOG.md b/flutter_inappwebview_windows/CHANGELOG.md index 409a43eaa..742f8f958 100644 --- a/flutter_inappwebview_windows/CHANGELOG.md +++ b/flutter_inappwebview_windows/CHANGELOG.md @@ -6,6 +6,9 @@ - Updated Microsoft.Windows.ImplementationLibrary to `1.0.260126.7` and Microsoft.Web.WebView2 to `1.0.4078.44` for current MSVC toolchains. - Fixed internal WebView host windows stealing focus from the Flutter window. +- Fixed owned popups (` dropdowns, the print preview pickers, context menus - +/// offset by the window origin. +void main() { + final source = + File('windows/in_app_webview/in_app_webview.cpp') + .readAsStringSync() + .replaceAll('\r\n', '\n'); + final setPosition = source.substring( + source.indexOf('void InAppWebView::setPosition('), + source.indexOf('void InAppWebView::setCursorPos('), + ); + + test('setPosition uses parent-client coordinates', () { + expect(setPosition, contains('SetWindowPos')); + expect(setPosition, contains('scaled_x,')); + expect(setPosition, contains('scaled_y,')); + }); + + test('setPosition does not reintroduce screen-coordinate math', () { + for (final banned in const [ + 'GetWindowRect', + 'GetSystemMetrics', + 'SM_CYCAPTION', + 'SM_CXPADDEDBORDER', + 'ClientToScreen', + ]) { + expect( + setPosition, + isNot(contains(banned)), + reason: '$banned belongs to screen-space positioning, which is wrong ' + 'for a WS_CHILD host window', + ); + } + }); +} diff --git a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp index 9829cb365..3fa9f3669 100644 --- a/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp +++ b/flutter_inappwebview_windows/windows/in_app_webview/in_app_webview.cpp @@ -3900,32 +3900,25 @@ namespace flutter_inappwebview_plugin void InAppWebView::setPosition(size_t x, size_t y, float scale_factor) { - if (!webViewController || !plugin || !plugin->registrar) { + if (!webViewController) { return; } - if (x >= 0 && y >= 0) { - scaleFactor_ = scale_factor; - auto scaled_x = static_cast(x * scale_factor); - auto scaled_y = static_cast(y * scale_factor); - widgetOffset_ = { scaled_x, scaled_y }; - - auto titleBarHeight = ((GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME)) * scale_factor) + GetSystemMetrics(SM_CXPADDEDBORDER); - auto borderWidth = (GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXPADDEDBORDER)) * scale_factor; - - RECT flutterWindowRect; - HWND flutterWindowHWnd = plugin->registrar->GetView()->GetNativeWindow(); - GetWindowRect(flutterWindowHWnd, &flutterWindowRect); - - HWND webViewHWnd; - if (succeededOrLog(webViewController->get_ParentWindow(&webViewHWnd))) { - ::SetWindowPos(webViewHWnd, - nullptr, - static_cast(flutterWindowRect.left + scaled_x - borderWidth), - static_cast(flutterWindowRect.top + scaled_y - titleBarHeight), - 0, 0, - SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - } + scaleFactor_ = scale_factor; + auto scaled_x = static_cast(x * scale_factor); + auto scaled_y = static_cast(y * scale_factor); + widgetOffset_ = { scaled_x, scaled_y }; + + HWND webViewHWnd; + if (succeededOrLog(webViewController->get_ParentWindow(&webViewHWnd))) { + // The host window is a WS_CHILD of the Flutter window, so SetWindowPos + // takes parent-client coordinates - exactly the widget offset. + ::SetWindowPos(webViewHWnd, + nullptr, + scaled_x, + scaled_y, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); } }