mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[windows] Add horizontal scroll support (flutter/engine#20668)
The embedding was only handling vertical scroll events from the OS; this adds horizontal as well. Fixes https://github.com/flutter/flutter/issues/60835
This commit is contained in:
parent
1830e42468
commit
f38bc774e7
@ -123,10 +123,10 @@ executable("flutter_windows_unittests") {
|
||||
sources = [
|
||||
"string_conversion_unittests.cc",
|
||||
"system_utils_unittests.cc",
|
||||
"testing/mock_win32_window.cc",
|
||||
"testing/mock_win32_window.h",
|
||||
"testing/win32_flutter_window_test.cc",
|
||||
"testing/win32_flutter_window_test.h",
|
||||
"testing/win32_window_test.cc",
|
||||
"testing/win32_window_test.h",
|
||||
"win32_dpi_utils_unittests.cc",
|
||||
"win32_flutter_window_unittests.cc",
|
||||
"win32_window_proc_delegate_manager_unittests.cc",
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
#include "flutter/shell/platform/windows/testing/mock_win32_window.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
MockWin32Window::MockWin32Window() : Win32Window(){};
|
||||
|
||||
MockWin32Window::~MockWin32Window() = default;
|
||||
|
||||
UINT MockWin32Window::GetDpi() {
|
||||
return GetCurrentDPI();
|
||||
}
|
||||
|
||||
void MockWin32Window::InjectWindowMessage(UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) {
|
||||
HandleMessage(message, wparam, lparam);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -0,0 +1,45 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "flutter/shell/platform/windows/win32_window.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
/// Mock for the Win32Window base class.
|
||||
class MockWin32Window : public Win32Window {
|
||||
public:
|
||||
MockWin32Window();
|
||||
virtual ~MockWin32Window();
|
||||
|
||||
// Prevent copying.
|
||||
MockWin32Window(MockWin32Window const&) = delete;
|
||||
MockWin32Window& operator=(MockWin32Window const&) = delete;
|
||||
|
||||
// Wrapper for GetCurrentDPI() which is a protected method.
|
||||
UINT GetDpi();
|
||||
|
||||
// Simulates a WindowProc message from the OS.
|
||||
void InjectWindowMessage(UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam);
|
||||
|
||||
MOCK_METHOD1(OnDpiScale, void(unsigned int));
|
||||
MOCK_METHOD2(OnResize, void(unsigned int, unsigned int));
|
||||
MOCK_METHOD2(OnPointerMove, void(double, double));
|
||||
MOCK_METHOD3(OnPointerDown, void(double, double, UINT));
|
||||
MOCK_METHOD3(OnPointerUp, void(double, double, UINT));
|
||||
MOCK_METHOD0(OnPointerLeave, void());
|
||||
MOCK_METHOD0(OnSetCursor, void());
|
||||
MOCK_METHOD1(OnText, void(const std::u16string&));
|
||||
MOCK_METHOD4(OnKey, void(int, int, int, char32_t));
|
||||
MOCK_METHOD2(OnScroll, void(double, double));
|
||||
MOCK_METHOD0(OnFontChange, void());
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -1,40 +0,0 @@
|
||||
#include "flutter/shell/platform/windows/testing/win32_window_test.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
Win32WindowTest::Win32WindowTest() : Win32Window(){};
|
||||
|
||||
Win32WindowTest::~Win32WindowTest() = default;
|
||||
|
||||
void Win32WindowTest::OnDpiScale(unsigned int dpi){};
|
||||
|
||||
void Win32WindowTest::OnResize(unsigned int width, unsigned int height) {}
|
||||
|
||||
void Win32WindowTest::OnPointerMove(double x, double y) {}
|
||||
|
||||
void Win32WindowTest::OnPointerDown(double x, double y, UINT button) {}
|
||||
|
||||
void Win32WindowTest::OnPointerUp(double x, double y, UINT button) {}
|
||||
|
||||
void Win32WindowTest::OnPointerLeave() {}
|
||||
|
||||
void Win32WindowTest::OnSetCursor() {}
|
||||
|
||||
void Win32WindowTest::OnText(const std::u16string& text) {}
|
||||
|
||||
void Win32WindowTest::OnKey(int key,
|
||||
int scancode,
|
||||
int action,
|
||||
char32_t character) {}
|
||||
|
||||
void Win32WindowTest::OnScroll(double delta_x, double delta_y) {}
|
||||
|
||||
void Win32WindowTest::OnFontChange() {}
|
||||
|
||||
UINT Win32WindowTest::GetDpi() {
|
||||
return GetCurrentDPI();
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -1,61 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "flutter/shell/platform/windows/win32_window.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
/// Test class for the Win32Window base class. Used to access protected methods
|
||||
/// for testing.
|
||||
class Win32WindowTest : public Win32Window {
|
||||
public:
|
||||
Win32WindowTest();
|
||||
virtual ~Win32WindowTest();
|
||||
|
||||
// Prevent copying.
|
||||
Win32WindowTest(Win32WindowTest const&) = delete;
|
||||
Win32WindowTest& operator=(Win32WindowTest const&) = delete;
|
||||
|
||||
// Wrapper for GetCurrentDPI() which is a protected method.
|
||||
UINT GetDpi();
|
||||
|
||||
// |Win32Window|
|
||||
void OnDpiScale(unsigned int dpi) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnResize(unsigned int width, unsigned int height) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnPointerMove(double x, double y) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnPointerDown(double x, double y, UINT button) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnPointerUp(double x, double y, UINT button) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnPointerLeave() override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnSetCursor() override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnText(const std::u16string& text) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnKey(int key, int scancode, int action, char32_t character) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnScroll(double delta_x, double delta_y) override;
|
||||
|
||||
// |Win32Window|
|
||||
void OnFontChange() override;
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -90,7 +90,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
||||
auto that = static_cast<Win32Window*>(cs->lpCreateParams);
|
||||
that->window_handle_ = window;
|
||||
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
||||
return that->MessageHandler(window, message, wparam, lparam);
|
||||
return that->HandleMessage(message, wparam, lparam);
|
||||
}
|
||||
|
||||
return DefWindowProc(window, message, wparam, lparam);
|
||||
@ -108,174 +108,169 @@ void Win32Window::TrackMouseLeaveEvent(HWND hwnd) {
|
||||
}
|
||||
|
||||
LRESULT
|
||||
Win32Window::MessageHandler(HWND hwnd,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
Win32Window::HandleMessage(UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
int xPos = 0, yPos = 0;
|
||||
UINT width = 0, height = 0;
|
||||
auto window =
|
||||
reinterpret_cast<Win32Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
UINT button_pressed = 0;
|
||||
|
||||
if (window != nullptr) {
|
||||
switch (message) {
|
||||
case kWmDpiChangedBeforeParent:
|
||||
current_dpi_ = GetDpiForHWND(window_handle_);
|
||||
window->OnDpiScale(current_dpi_);
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
width = LOWORD(lparam);
|
||||
height = HIWORD(lparam);
|
||||
switch (message) {
|
||||
case kWmDpiChangedBeforeParent:
|
||||
current_dpi_ = GetDpiForHWND(window_handle_);
|
||||
OnDpiScale(current_dpi_);
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
width = LOWORD(lparam);
|
||||
height = HIWORD(lparam);
|
||||
|
||||
current_width_ = width;
|
||||
current_height_ = height;
|
||||
window->HandleResize(width, height);
|
||||
break;
|
||||
case WM_FONTCHANGE:
|
||||
window->OnFontChange();
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
window->TrackMouseLeaveEvent(hwnd);
|
||||
current_width_ = width;
|
||||
current_height_ = height;
|
||||
HandleResize(width, height);
|
||||
break;
|
||||
case WM_FONTCHANGE:
|
||||
OnFontChange();
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
TrackMouseLeaveEvent(window_handle_);
|
||||
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
window->OnPointerMove(static_cast<double>(xPos),
|
||||
static_cast<double>(yPos));
|
||||
break;
|
||||
case WM_MOUSELEAVE:;
|
||||
window->OnPointerLeave();
|
||||
// Once the tracked event is received, the TrackMouseEvent function
|
||||
// resets. Set to false to make sure it's called once mouse movement is
|
||||
// detected again.
|
||||
tracking_mouse_leave_ = false;
|
||||
break;
|
||||
case WM_SETCURSOR: {
|
||||
UINT hit_test_result = LOWORD(lparam);
|
||||
if (hit_test_result == HTCLIENT) {
|
||||
window->OnSetCursor();
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
OnPointerMove(static_cast<double>(xPos), static_cast<double>(yPos));
|
||||
break;
|
||||
case WM_MOUSELEAVE:;
|
||||
OnPointerLeave();
|
||||
// Once the tracked event is received, the TrackMouseEvent function
|
||||
// resets. Set to false to make sure it's called once mouse movement is
|
||||
// detected again.
|
||||
tracking_mouse_leave_ = false;
|
||||
break;
|
||||
case WM_SETCURSOR: {
|
||||
UINT hit_test_result = LOWORD(lparam);
|
||||
if (hit_test_result == HTCLIENT) {
|
||||
OnSetCursor();
|
||||
return TRUE;
|
||||
}
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_XBUTTONDOWN:
|
||||
if (message == WM_LBUTTONDOWN) {
|
||||
// Capture the pointer in case the user drags outside the client area.
|
||||
// In this case, the "mouse leave" event is delayed until the user
|
||||
// releases the button. It's only activated on left click given that
|
||||
// it's more common for apps to handle dragging with only the left
|
||||
// button.
|
||||
SetCapture(hwnd);
|
||||
}
|
||||
button_pressed = message;
|
||||
if (message == WM_XBUTTONDOWN) {
|
||||
button_pressed = GET_XBUTTON_WPARAM(wparam);
|
||||
}
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
window->OnPointerDown(static_cast<double>(xPos),
|
||||
static_cast<double>(yPos), button_pressed);
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP:
|
||||
if (message == WM_LBUTTONUP) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
button_pressed = message;
|
||||
if (message == WM_XBUTTONUP) {
|
||||
button_pressed = GET_XBUTTON_WPARAM(wparam);
|
||||
}
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
window->OnPointerUp(static_cast<double>(xPos),
|
||||
static_cast<double>(yPos), button_pressed);
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
window->OnScroll(
|
||||
0.0, -(static_cast<short>(HIWORD(wparam)) / (double)WHEEL_DELTA));
|
||||
break;
|
||||
case WM_UNICHAR: {
|
||||
// Tell third-pary app, we can support Unicode.
|
||||
if (wparam == UNICODE_NOCHAR)
|
||||
return TRUE;
|
||||
// DefWindowProc will send WM_CHAR for this WM_UNICHAR.
|
||||
break;
|
||||
}
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR: {
|
||||
static wchar_t s_pending_high_surrogate = 0;
|
||||
|
||||
wchar_t character = static_cast<wchar_t>(wparam);
|
||||
std::u16string text({character});
|
||||
char32_t code_point = character;
|
||||
if (IS_HIGH_SURROGATE(character)) {
|
||||
// Save to send later with the trailing surrogate.
|
||||
s_pending_high_surrogate = character;
|
||||
} else if (IS_LOW_SURROGATE(character) &&
|
||||
s_pending_high_surrogate != 0) {
|
||||
text.insert(text.begin(), s_pending_high_surrogate);
|
||||
// Merge the surrogate pairs for the key event.
|
||||
code_point =
|
||||
CodePointFromSurrogatePair(s_pending_high_surrogate, character);
|
||||
s_pending_high_surrogate = 0;
|
||||
}
|
||||
|
||||
// Of the messages handled here, only WM_CHAR should be treated as
|
||||
// characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR
|
||||
// will be incorporated into a later WM_CHAR with the full character.
|
||||
// Also filter out:
|
||||
// - Lead surrogates, which like dead keys will be send once combined.
|
||||
// - ASCII control characters, which are sent as WM_CHAR events for all
|
||||
// control key shortcuts.
|
||||
if (message == WM_CHAR && s_pending_high_surrogate == 0 &&
|
||||
character >= u' ') {
|
||||
window->OnText(text);
|
||||
}
|
||||
|
||||
// All key presses that generate a character should be sent from
|
||||
// WM_CHAR. In order to send the full key press information, the keycode
|
||||
// is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN.
|
||||
if (keycode_for_char_message_ != 0) {
|
||||
const unsigned int scancode = (lparam >> 16) & 0xff;
|
||||
window->OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN,
|
||||
code_point);
|
||||
keycode_for_char_message_ = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
const bool is_keydown_message =
|
||||
(message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
|
||||
// Check if this key produces a character. If so, the key press should
|
||||
// be sent with the character produced at WM_CHAR. Store the produced
|
||||
// keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR.
|
||||
const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR);
|
||||
if (character > 0 && is_keydown_message) {
|
||||
keycode_for_char_message_ = wparam;
|
||||
break;
|
||||
}
|
||||
unsigned int keyCode(wparam);
|
||||
const unsigned int scancode = (lparam >> 16) & 0xff;
|
||||
// If the key is a modifier, get its side.
|
||||
if (keyCode == VK_SHIFT || keyCode == VK_MENU ||
|
||||
keyCode == VK_CONTROL) {
|
||||
keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
|
||||
}
|
||||
const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP;
|
||||
window->OnKey(keyCode, scancode, action, 0);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return DefWindowProc(hwnd, message, wparam, lparam);
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_XBUTTONDOWN:
|
||||
if (message == WM_LBUTTONDOWN) {
|
||||
// Capture the pointer in case the user drags outside the client area.
|
||||
// In this case, the "mouse leave" event is delayed until the user
|
||||
// releases the button. It's only activated on left click given that
|
||||
// it's more common for apps to handle dragging with only the left
|
||||
// button.
|
||||
SetCapture(window_handle_);
|
||||
}
|
||||
button_pressed = message;
|
||||
if (message == WM_XBUTTONDOWN) {
|
||||
button_pressed = GET_XBUTTON_WPARAM(wparam);
|
||||
}
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
OnPointerDown(static_cast<double>(xPos), static_cast<double>(yPos),
|
||||
button_pressed);
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP:
|
||||
if (message == WM_LBUTTONUP) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
button_pressed = message;
|
||||
if (message == WM_XBUTTONUP) {
|
||||
button_pressed = GET_XBUTTON_WPARAM(wparam);
|
||||
}
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
OnPointerUp(static_cast<double>(xPos), static_cast<double>(yPos),
|
||||
button_pressed);
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
OnScroll(0.0, -(static_cast<short>(HIWORD(wparam)) /
|
||||
static_cast<double>(WHEEL_DELTA)));
|
||||
break;
|
||||
case WM_MOUSEHWHEEL:
|
||||
OnScroll((static_cast<short>(HIWORD(wparam)) /
|
||||
static_cast<double>(WHEEL_DELTA)),
|
||||
0.0);
|
||||
break;
|
||||
case WM_UNICHAR: {
|
||||
// Tell third-pary app, we can support Unicode.
|
||||
if (wparam == UNICODE_NOCHAR)
|
||||
return TRUE;
|
||||
// DefWindowProc will send WM_CHAR for this WM_UNICHAR.
|
||||
break;
|
||||
}
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR: {
|
||||
static wchar_t s_pending_high_surrogate = 0;
|
||||
|
||||
wchar_t character = static_cast<wchar_t>(wparam);
|
||||
std::u16string text({character});
|
||||
char32_t code_point = character;
|
||||
if (IS_HIGH_SURROGATE(character)) {
|
||||
// Save to send later with the trailing surrogate.
|
||||
s_pending_high_surrogate = character;
|
||||
} else if (IS_LOW_SURROGATE(character) && s_pending_high_surrogate != 0) {
|
||||
text.insert(text.begin(), s_pending_high_surrogate);
|
||||
// Merge the surrogate pairs for the key event.
|
||||
code_point =
|
||||
CodePointFromSurrogatePair(s_pending_high_surrogate, character);
|
||||
s_pending_high_surrogate = 0;
|
||||
}
|
||||
|
||||
// Of the messages handled here, only WM_CHAR should be treated as
|
||||
// characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR
|
||||
// will be incorporated into a later WM_CHAR with the full character.
|
||||
// Also filter out:
|
||||
// - Lead surrogates, which like dead keys will be send once combined.
|
||||
// - ASCII control characters, which are sent as WM_CHAR events for all
|
||||
// control key shortcuts.
|
||||
if (message == WM_CHAR && s_pending_high_surrogate == 0 &&
|
||||
character >= u' ') {
|
||||
OnText(text);
|
||||
}
|
||||
|
||||
// All key presses that generate a character should be sent from
|
||||
// WM_CHAR. In order to send the full key press information, the keycode
|
||||
// is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN.
|
||||
if (keycode_for_char_message_ != 0) {
|
||||
const unsigned int scancode = (lparam >> 16) & 0xff;
|
||||
OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN, code_point);
|
||||
keycode_for_char_message_ = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
const bool is_keydown_message =
|
||||
(message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
|
||||
// Check if this key produces a character. If so, the key press should
|
||||
// be sent with the character produced at WM_CHAR. Store the produced
|
||||
// keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR.
|
||||
const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR);
|
||||
if (character > 0 && is_keydown_message) {
|
||||
keycode_for_char_message_ = wparam;
|
||||
break;
|
||||
}
|
||||
unsigned int keyCode(wparam);
|
||||
const unsigned int scancode = (lparam >> 16) & 0xff;
|
||||
// If the key is a modifier, get its side.
|
||||
if (keyCode == VK_SHIFT || keyCode == VK_MENU || keyCode == VK_CONTROL) {
|
||||
keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
|
||||
}
|
||||
const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP;
|
||||
OnKey(keyCode, scancode, action, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(window_handle_, message, wparam, lparam);
|
||||
|
||||
@ -52,10 +52,9 @@ class Win32Window {
|
||||
// size change and DPI. Delegates handling of these to member overloads that
|
||||
// inheriting classes can handle.
|
||||
LRESULT
|
||||
MessageHandler(HWND window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
HandleMessage(UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
|
||||
// When WM_DPICHANGE process it using |hWnd|, |wParam|. If
|
||||
// |top_level| is set, extract the suggested new size from |lParam| and resize
|
||||
|
||||
@ -2,21 +2,40 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/windows/testing/win32_window_test.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_win32_window.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(Win32WindowTest, CreateDestroy) {
|
||||
Win32WindowTest window;
|
||||
TEST(MockWin32Window, CreateDestroy) {
|
||||
MockWin32Window window;
|
||||
ASSERT_TRUE(TRUE);
|
||||
}
|
||||
|
||||
TEST(Win32WindowTest, GetDpiAfterCreate) {
|
||||
Win32WindowTest window;
|
||||
TEST(MockWin32Window, GetDpiAfterCreate) {
|
||||
MockWin32Window window;
|
||||
ASSERT_TRUE(window.GetDpi() > 0);
|
||||
}
|
||||
|
||||
TEST(MockWin32Window, VerticalScroll) {
|
||||
MockWin32Window window;
|
||||
const int scroll_amount = 10;
|
||||
// Vertical scroll should be passed along, adjusted for scroll tick size
|
||||
// and direction.
|
||||
EXPECT_CALL(window, OnScroll(0, -scroll_amount / 120.0)).Times(1);
|
||||
|
||||
window.InjectWindowMessage(WM_MOUSEWHEEL, MAKEWPARAM(0, scroll_amount), 0);
|
||||
}
|
||||
|
||||
TEST(MockWin32Window, HorizontalScroll) {
|
||||
MockWin32Window window;
|
||||
const int scroll_amount = 10;
|
||||
// Vertical scroll should be passed along, adjusted for scroll tick size.
|
||||
EXPECT_CALL(window, OnScroll(scroll_amount / 120.0, 0)).Times(1);
|
||||
|
||||
window.InjectWindowMessage(WM_MOUSEHWHEEL, MAKEWPARAM(0, scroll_amount), 0);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user