未验证 提交 6726a467 编写于 作者: S stuartmorgan 提交者: GitHub

Implement cursor support for Windows (#19459)

Implements the basic engine support for Windows for
https://github.com/flutter/flutter/issues/31952
上级 7d5d8fa4
......@@ -1310,6 +1310,8 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flu
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc
FILE: ../../../flutter/shell/platform/windows/cursor_handler.h
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
......
......@@ -41,6 +41,8 @@ source_set("flutter_windows_source") {
sources = [
"angle_surface_manager.cc",
"angle_surface_manager.h",
"cursor_handler.cc",
"cursor_handler.h",
"flutter_windows.cc",
"flutter_windows_view.cc",
"flutter_windows_view.h",
......
// 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 "flutter/shell/platform/windows/cursor_handler.h"
#include <windows.h>
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_method_codec.h"
static constexpr char kChannelName[] = "flutter/mousecursor";
static constexpr char kActivateSystemCursorMethod[] = "activateSystemCursor";
static constexpr char kKindKey[] = "kind";
namespace flutter {
CursorHandler::CursorHandler(flutter::BinaryMessenger* messenger,
WindowBindingHandler* delegate)
: channel_(std::make_unique<flutter::MethodChannel<EncodableValue>>(
messenger,
kChannelName,
&flutter::StandardMethodCodec::GetInstance())),
delegate_(delegate) {
channel_->SetMethodCallHandler(
[this](const flutter::MethodCall<EncodableValue>& call,
std::unique_ptr<flutter::MethodResult<EncodableValue>> result) {
HandleMethodCall(call, std::move(result));
});
}
void CursorHandler::HandleMethodCall(
const flutter::MethodCall<EncodableValue>& method_call,
std::unique_ptr<flutter::MethodResult<EncodableValue>> result) {
const std::string& method = method_call.method_name();
if (method.compare(kActivateSystemCursorMethod) == 0) {
const flutter::EncodableMap& arguments =
method_call.arguments()->MapValue();
auto kind_iter = arguments.find(EncodableValue(kKindKey));
if (kind_iter == arguments.end()) {
result->Error("Argument error",
"Missing argument while trying to activate system cursor");
}
const std::string& kind = kind_iter->second.StringValue();
delegate_->UpdateFlutterCursor(kind);
result->Success();
} else {
result->NotImplemented();
}
}
} // namespace flutter
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/encodable_value.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
namespace flutter {
// Handler for the cursor system channel.
class CursorHandler {
public:
explicit CursorHandler(flutter::BinaryMessenger* messenger,
WindowBindingHandler* delegate);
private:
// Called when a method is called on |channel_|;
void HandleMethodCall(
const flutter::MethodCall<EncodableValue>& method_call,
std::unique_ptr<flutter::MethodResult<EncodableValue>> result);
// The MethodChannel used for communication with the Flutter engine.
std::unique_ptr<flutter::MethodChannel<EncodableValue>> channel_;
// The delegate for cursor updates.
WindowBindingHandler* delegate_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_
......@@ -20,9 +20,6 @@
#include "flutter/shell/platform/common/cpp/path_utils.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/key_event_handler.h"
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
#include "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
#include "flutter/shell/platform/windows/win32_flutter_window.h"
#include "flutter/shell/platform/windows/win32_platform_handler.h"
......
......@@ -65,6 +65,8 @@ void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) {
std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
platform_handler_ = std::make_unique<flutter::PlatformHandler>(
internal_plugin_messenger, this);
cursor_handler_ = std::make_unique<flutter::CursorHandler>(
internal_plugin_messenger, binding_handler_.get());
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
......
......@@ -14,6 +14,7 @@
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/angle_surface_manager.h"
#include "flutter/shell/platform/windows/cursor_handler.h"
#include "flutter/shell/platform/windows/key_event_handler.h"
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
......@@ -213,6 +214,9 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate {
// Handler for the flutter/platform channel.
std::unique_ptr<flutter::PlatformHandler> platform_handler_;
// Handler for cursor events.
std::unique_ptr<flutter::CursorHandler> cursor_handler_;
// Currently configured WindowBindingHandler for view.
std::unique_ptr<flutter::WindowBindingHandler> binding_handler_;
};
......
......@@ -19,6 +19,8 @@ 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,
......
......@@ -41,6 +41,9 @@ class Win32WindowTest : public Win32Window {
// |Win32Window|
void OnPointerLeave() override;
// |Win32Window|
void OnSetCursor() override;
// |Win32Window|
void OnText(const std::u16string& text) override;
......
#include "flutter/shell/platform/windows/win32_flutter_window.h"
#include <chrono>
#include <map>
namespace flutter {
namespace {
// The Windows DPI system is based on this
// constant for machines running at 100% scaling.
constexpr int base_dpi = 96;
......@@ -12,9 +15,33 @@ constexpr int base_dpi = 96;
// arbitrarily to get something that feels reasonable.
constexpr int kScrollOffsetMultiplier = 20;
// Maps a Flutter cursor name to an HCURSOR.
//
// Returns the arrow cursor for unknown constants.
static HCURSOR GetCursorByName(const std::string& cursor_name) {
static auto* cursors = new std::map<std::string, const wchar_t*>{
{"none", nullptr},
{"basic", IDC_ARROW},
{"click", IDC_HAND},
{"text", IDC_IBEAM},
{"forbidden", IDC_NO},
{"horizontalDoubleArrow", IDC_SIZEWE},
{"verticalDoubleArrow", IDC_SIZENS},
};
const wchar_t* idc_name = IDC_ARROW;
auto it = cursors->find(cursor_name);
if (it != cursors->end()) {
idc_name = it->second;
}
return ::LoadCursor(nullptr, idc_name);
}
} // namespace
Win32FlutterWindow::Win32FlutterWindow(int width, int height)
: binding_handler_delegate_(nullptr) {
Win32Window::InitializeChild("FLUTTERVIEW", width, height);
current_cursor_ = ::LoadCursor(nullptr, IDC_ARROW);
}
Win32FlutterWindow::~Win32FlutterWindow() {}
......@@ -35,6 +62,10 @@ PhysicalWindowBounds Win32FlutterWindow::GetPhysicalWindowBounds() {
return {GetCurrentWidth(), GetCurrentHeight()};
}
void Win32FlutterWindow::UpdateFlutterCursor(const std::string& cursor_name) {
current_cursor_ = GetCursorByName(cursor_name);
}
// Translates button codes from Win32 API to FlutterPointerMouseButtons.
static uint64_t ConvertWinButtonToFlutterButton(UINT button) {
switch (button) {
......@@ -90,6 +121,10 @@ void Win32FlutterWindow::OnPointerLeave() {
binding_handler_delegate_->OnPointerLeave();
}
void Win32FlutterWindow::OnSetCursor() {
::SetCursor(current_cursor_);
}
void Win32FlutterWindow::OnText(const std::u16string& text) {
binding_handler_delegate_->OnText(text);
}
......
......@@ -12,7 +12,6 @@
#include <vector>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/win32_window.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
......@@ -48,6 +47,9 @@ class Win32FlutterWindow : public Win32Window, public WindowBindingHandler {
// |Win32Window|
void OnPointerLeave() override;
// |Win32Window|
void OnSetCursor() override;
// |Win32Window|
void OnText(const std::u16string& text) override;
......@@ -72,9 +74,16 @@ class Win32FlutterWindow : public Win32Window, public WindowBindingHandler {
// |FlutterWindowBindingHandler|
PhysicalWindowBounds GetPhysicalWindowBounds() override;
// |FlutterWindowBindingHandler|
void UpdateFlutterCursor(const std::string& cursor_name) override;
private:
// A pointer to a FlutterWindowsView that can be used to update engine
// windowing and input state.
WindowBindingHandlerDelegate* binding_handler_delegate_;
// The last cursor set by Flutter. Defaults to the arrow cursor.
HCURSOR current_cursor_;
};
} // namespace flutter
......
......@@ -150,6 +150,14 @@ Win32Window::MessageHandler(HWND hwnd,
// 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;
}
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
......
......@@ -86,6 +86,9 @@ class Win32Window {
// Called when the mouse leaves the window.
virtual void OnPointerLeave() = 0;
// Called when the cursor should be set for the client area.
virtual void OnSetCursor() = 0;
// Called when text input occurs.
virtual void OnText(const std::u16string& text) = 0;
......
......@@ -5,13 +5,12 @@
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_H_
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include <windows.h>
#include <string>
#include <variant>
#include <windows.h>
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
namespace flutter {
......@@ -45,6 +44,10 @@ class WindowBindingHandler {
// Returns the bounds of the backing window in physical pixels.
virtual PhysicalWindowBounds GetPhysicalWindowBounds() = 0;
// Sets the cursor that should be used when the mouse is over the Flutter
// content. See mouse_cursor.dart for the values and meanings of cursor_name.
virtual void UpdateFlutterCursor(const std::string& cursor_name) = 0;
};
} // namespace flutter
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册