Skip to content

Commit 6726a46

Browse files
Implement cursor support for Windows (flutter#19459)
Implements the basic engine support for Windows for flutter#31952
1 parent 7d5d8fa commit 6726a46

14 files changed

+167
-7
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,8 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flu
13101310
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
13111311
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h
13121312
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
1313+
FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc
1314+
FILE: ../../../flutter/shell/platform/windows/cursor_handler.h
13131315
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
13141316
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
13151317
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h

shell/platform/windows/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ source_set("flutter_windows_source") {
4141
sources = [
4242
"angle_surface_manager.cc",
4343
"angle_surface_manager.h",
44+
"cursor_handler.cc",
45+
"cursor_handler.h",
4446
"flutter_windows.cc",
4547
"flutter_windows_view.cc",
4648
"flutter_windows_view.h",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/windows/cursor_handler.h"
6+
7+
#include <windows.h>
8+
9+
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_method_codec.h"
10+
11+
static constexpr char kChannelName[] = "flutter/mousecursor";
12+
13+
static constexpr char kActivateSystemCursorMethod[] = "activateSystemCursor";
14+
15+
static constexpr char kKindKey[] = "kind";
16+
17+
namespace flutter {
18+
19+
CursorHandler::CursorHandler(flutter::BinaryMessenger* messenger,
20+
WindowBindingHandler* delegate)
21+
: channel_(std::make_unique<flutter::MethodChannel<EncodableValue>>(
22+
messenger,
23+
kChannelName,
24+
&flutter::StandardMethodCodec::GetInstance())),
25+
delegate_(delegate) {
26+
channel_->SetMethodCallHandler(
27+
[this](const flutter::MethodCall<EncodableValue>& call,
28+
std::unique_ptr<flutter::MethodResult<EncodableValue>> result) {
29+
HandleMethodCall(call, std::move(result));
30+
});
31+
}
32+
33+
void CursorHandler::HandleMethodCall(
34+
const flutter::MethodCall<EncodableValue>& method_call,
35+
std::unique_ptr<flutter::MethodResult<EncodableValue>> result) {
36+
const std::string& method = method_call.method_name();
37+
if (method.compare(kActivateSystemCursorMethod) == 0) {
38+
const flutter::EncodableMap& arguments =
39+
method_call.arguments()->MapValue();
40+
auto kind_iter = arguments.find(EncodableValue(kKindKey));
41+
if (kind_iter == arguments.end()) {
42+
result->Error("Argument error",
43+
"Missing argument while trying to activate system cursor");
44+
}
45+
const std::string& kind = kind_iter->second.StringValue();
46+
delegate_->UpdateFlutterCursor(kind);
47+
result->Success();
48+
} else {
49+
result->NotImplemented();
50+
}
51+
}
52+
53+
} // namespace flutter
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_
7+
8+
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
9+
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/encodable_value.h"
10+
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
11+
#include "flutter/shell/platform/windows/public/flutter_windows.h"
12+
#include "flutter/shell/platform/windows/window_binding_handler.h"
13+
14+
namespace flutter {
15+
16+
// Handler for the cursor system channel.
17+
class CursorHandler {
18+
public:
19+
explicit CursorHandler(flutter::BinaryMessenger* messenger,
20+
WindowBindingHandler* delegate);
21+
22+
private:
23+
// Called when a method is called on |channel_|;
24+
void HandleMethodCall(
25+
const flutter::MethodCall<EncodableValue>& method_call,
26+
std::unique_ptr<flutter::MethodResult<EncodableValue>> result);
27+
28+
// The MethodChannel used for communication with the Flutter engine.
29+
std::unique_ptr<flutter::MethodChannel<EncodableValue>> channel_;
30+
31+
// The delegate for cursor updates.
32+
WindowBindingHandler* delegate_;
33+
};
34+
35+
} // namespace flutter
36+
37+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CURSOR_HANDLER_H_

shell/platform/windows/flutter_windows.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
#include "flutter/shell/platform/common/cpp/path_utils.h"
2121
#include "flutter/shell/platform/embedder/embedder.h"
2222
#include "flutter/shell/platform/windows/flutter_windows_view.h"
23-
#include "flutter/shell/platform/windows/key_event_handler.h"
24-
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
25-
#include "flutter/shell/platform/windows/text_input_plugin.h"
2623
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
2724
#include "flutter/shell/platform/windows/win32_flutter_window.h"
2825
#include "flutter/shell/platform/windows/win32_platform_handler.h"

shell/platform/windows/flutter_windows_view.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) {
6565
std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
6666
platform_handler_ = std::make_unique<flutter::PlatformHandler>(
6767
internal_plugin_messenger, this);
68+
cursor_handler_ = std::make_unique<flutter::CursorHandler>(
69+
internal_plugin_messenger, binding_handler_.get());
6870

6971
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
7072

shell/platform/windows/flutter_windows_view.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
1515
#include "flutter/shell/platform/embedder/embedder.h"
1616
#include "flutter/shell/platform/windows/angle_surface_manager.h"
17+
#include "flutter/shell/platform/windows/cursor_handler.h"
1718
#include "flutter/shell/platform/windows/key_event_handler.h"
1819
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
1920
#include "flutter/shell/platform/windows/public/flutter_windows.h"
@@ -213,6 +214,9 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate {
213214
// Handler for the flutter/platform channel.
214215
std::unique_ptr<flutter::PlatformHandler> platform_handler_;
215216

217+
// Handler for cursor events.
218+
std::unique_ptr<flutter::CursorHandler> cursor_handler_;
219+
216220
// Currently configured WindowBindingHandler for view.
217221
std::unique_ptr<flutter::WindowBindingHandler> binding_handler_;
218222
};

shell/platform/windows/testing/win32_window_test.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ void Win32WindowTest::OnPointerUp(double x, double y, UINT button) {}
1919

2020
void Win32WindowTest::OnPointerLeave() {}
2121

22+
void Win32WindowTest::OnSetCursor() {}
23+
2224
void Win32WindowTest::OnText(const std::u16string& text) {}
2325

2426
void Win32WindowTest::OnKey(int key,

shell/platform/windows/testing/win32_window_test.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class Win32WindowTest : public Win32Window {
4141
// |Win32Window|
4242
void OnPointerLeave() override;
4343

44+
// |Win32Window|
45+
void OnSetCursor() override;
46+
4447
// |Win32Window|
4548
void OnText(const std::u16string& text) override;
4649

shell/platform/windows/win32_flutter_window.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "flutter/shell/platform/windows/win32_flutter_window.h"
22

33
#include <chrono>
4+
#include <map>
45

56
namespace flutter {
67

8+
namespace {
9+
710
// The Windows DPI system is based on this
811
// constant for machines running at 100% scaling.
912
constexpr int base_dpi = 96;
@@ -12,9 +15,33 @@ constexpr int base_dpi = 96;
1215
// arbitrarily to get something that feels reasonable.
1316
constexpr int kScrollOffsetMultiplier = 20;
1417

18+
// Maps a Flutter cursor name to an HCURSOR.
19+
//
20+
// Returns the arrow cursor for unknown constants.
21+
static HCURSOR GetCursorByName(const std::string& cursor_name) {
22+
static auto* cursors = new std::map<std::string, const wchar_t*>{
23+
{"none", nullptr},
24+
{"basic", IDC_ARROW},
25+
{"click", IDC_HAND},
26+
{"text", IDC_IBEAM},
27+
{"forbidden", IDC_NO},
28+
{"horizontalDoubleArrow", IDC_SIZEWE},
29+
{"verticalDoubleArrow", IDC_SIZENS},
30+
};
31+
const wchar_t* idc_name = IDC_ARROW;
32+
auto it = cursors->find(cursor_name);
33+
if (it != cursors->end()) {
34+
idc_name = it->second;
35+
}
36+
return ::LoadCursor(nullptr, idc_name);
37+
}
38+
39+
} // namespace
40+
1541
Win32FlutterWindow::Win32FlutterWindow(int width, int height)
1642
: binding_handler_delegate_(nullptr) {
1743
Win32Window::InitializeChild("FLUTTERVIEW", width, height);
44+
current_cursor_ = ::LoadCursor(nullptr, IDC_ARROW);
1845
}
1946

2047
Win32FlutterWindow::~Win32FlutterWindow() {}
@@ -35,6 +62,10 @@ PhysicalWindowBounds Win32FlutterWindow::GetPhysicalWindowBounds() {
3562
return {GetCurrentWidth(), GetCurrentHeight()};
3663
}
3764

65+
void Win32FlutterWindow::UpdateFlutterCursor(const std::string& cursor_name) {
66+
current_cursor_ = GetCursorByName(cursor_name);
67+
}
68+
3869
// Translates button codes from Win32 API to FlutterPointerMouseButtons.
3970
static uint64_t ConvertWinButtonToFlutterButton(UINT button) {
4071
switch (button) {
@@ -90,6 +121,10 @@ void Win32FlutterWindow::OnPointerLeave() {
90121
binding_handler_delegate_->OnPointerLeave();
91122
}
92123

124+
void Win32FlutterWindow::OnSetCursor() {
125+
::SetCursor(current_cursor_);
126+
}
127+
93128
void Win32FlutterWindow::OnText(const std::u16string& text) {
94129
binding_handler_delegate_->OnText(text);
95130
}

0 commit comments

Comments
 (0)