20 "createCustomCursor/windows";
42 "deleteCustomCursor/windows";
56 channel_->SetMethodCallHandler(
59 HandleMethodCall(call, std::move(result));
63void CursorHandler::HandleMethodCall(
66 const std::string& method =
method_call.method_name();
68 const auto& arguments = std::get<EncodableMap>(*
method_call.arguments());
70 if (kind_iter == arguments.end()) {
71 result->Error(
"Argument error",
72 "Missing argument while trying to activate system cursor");
75 const auto& kind = std::get<std::string>(kind_iter->second);
79 const auto& arguments = std::get<EncodableMap>(*
method_call.arguments());
82 if (name_iter == arguments.end()) {
85 "Missing argument name while trying to customize system cursor");
88 auto name = std::get<std::string>(name_iter->second);
91 if (buffer_iter == arguments.end()) {
94 "Missing argument buffer while trying to customize system cursor");
97 auto buffer = std::get<std::vector<uint8_t>>(buffer_iter->second);
100 if (width_iter == arguments.end()) {
103 "Missing argument width while trying to customize system cursor");
106 auto width = std::get<int>(width_iter->second);
109 if (height_iter == arguments.end()) {
112 "Missing argument height while trying to customize system cursor");
115 auto height = std::get<int>(height_iter->second);
118 if (hot_x_iter == arguments.end()) {
121 "Missing argument hotX while trying to customize system cursor");
124 auto hot_x = std::get<double>(hot_x_iter->second);
127 if (hot_y_iter == arguments.end()) {
130 "Missing argument hotY while trying to customize system cursor");
133 auto hot_y = std::get<double>(hot_y_iter->second);
135 if (cursor ==
nullptr) {
136 result->Error(
"Argument error",
137 "Argument must contains a valid rawBGRA bitmap");
141 custom_cursors_.emplace(
name, std::move(cursor));
144 const auto& arguments = std::get<EncodableMap>(*
method_call.arguments());
147 if (name_iter == arguments.end()) {
148 result->Error(
"Argument error",
149 "Missing argument key while trying to set a custom cursor");
152 auto name = std::get<std::string>(name_iter->second);
153 if (custom_cursors_.find(
name) == custom_cursors_.end()) {
156 "The custom cursor identified by the argument key cannot be found");
159 HCURSOR cursor = custom_cursors_[
name];
163 const auto& arguments = std::get<EncodableMap>(*
method_call.arguments());
166 if (name_iter == arguments.end()) {
169 "Missing argument key while trying to delete a custom cursor");
172 auto name = std::get<std::string>(name_iter->second);
173 auto it = custom_cursors_.find(
name);
176 if (it != custom_cursors_.end()) {
177 DeleteObject(it->second);
178 custom_cursors_.erase(it);
182 result->NotImplemented();
191 HCURSOR cursor =
nullptr;
192 HDC display_dc = GetDC(NULL);
195 memset(&bmi, 0,
sizeof(bmi));
196 bmi.bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
197 bmi.bmiHeader.biWidth =
width;
198 bmi.bmiHeader.biHeight = -
height;
199 bmi.bmiHeader.biPlanes = 1;
200 bmi.bmiHeader.biBitCount = 32;
201 bmi.bmiHeader.biCompression = BI_RGB;
206 CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (
void**)&pixels, 0, 0);
207 ReleaseDC(0, display_dc);
208 if (!bitmap || !pixels) {
211 int bytes_per_line =
width * 4;
213 memcpy(pixels +
y * bytes_per_line, &
buffer[bytes_per_line *
y],
220 icon_info.xHotspot = hot_x;
221 icon_info.yHotspot = hot_y;
222 icon_info.hbmMask = mask;
223 icon_info.hbmColor = bitmap;
224 cursor = CreateIconIndirect(&icon_info);
226 DeleteObject(bitmap);
231 HDC h_dc = ::GetDC(NULL);
232 HDC h_main_dc = ::CreateCompatibleDC(h_dc);
233 HDC h_and_mask_dc = ::CreateCompatibleDC(h_dc);
237 ::GetObject(bitmap,
sizeof(BITMAP), &bm);
238 mask_bitmap = ::CreateCompatibleBitmap(h_dc, bm.bmWidth, bm.bmHeight);
241 HBITMAP h_old_main_bitmap = (HBITMAP)::SelectObject(h_main_dc, bitmap);
242 HBITMAP h_old_and_mask_bitmap =
243 (HBITMAP)::SelectObject(h_and_mask_dc, mask_bitmap);
246 COLORREF main_bit_pixel;
247 for (
int x = 0;
x < bm.bmWidth; ++
x) {
248 for (
int y = 0;
y < bm.bmHeight; ++
y) {
249 main_bit_pixel = ::GetPixel(h_main_dc,
x,
y);
250 if (main_bit_pixel == RGB(0, 0, 0)) {
251 ::SetPixel(h_and_mask_dc,
x,
y, RGB(255, 255, 255));
253 ::SetPixel(h_and_mask_dc,
x,
y, RGB(0, 0, 0));
257 ::SelectObject(h_main_dc, h_old_main_bitmap);
258 ::SelectObject(h_and_mask_dc, h_old_and_mask_bitmap);
260 ::DeleteDC(h_and_mask_dc);
261 ::DeleteDC(h_main_dc);
263 ::ReleaseDC(NULL, h_dc);
static NSString *const kActivateSystemCursorMethod
static NSString *const kKindKey
CursorHandler(flutter::BinaryMessenger *messenger, flutter::FlutterWindowsEngine *engine)
void UpdateFlutterCursor(const std::string &cursor_name) const
void SetFlutterCursor(HCURSOR cursor) const
static constexpr char kDeleteCustomCursorMethod[]
static constexpr char kActivateSystemCursorMethod[]
static constexpr char kCustomCursorHotXKey[]
static constexpr char kCustomCursorWidthKey[]
static constexpr char kKindKey[]
static constexpr char kChannelName[]
static constexpr char kCustomCursorHotYKey[]
static constexpr char kCustomCursorNameKey[]
static constexpr char kCreateCustomCursorMethod[]
static constexpr char kSetCustomCursorMethod[]
static constexpr char kCustomCursorBufferKey[]
static constexpr char kCursorError[]
static constexpr char kCustomCursorHeightKey[]
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
void GetMaskBitmaps(HBITMAP bitmap, HBITMAP &mask_bitmap)
DEF_SWITCHES_START aot vmservice shared library name
HCURSOR GetCursorFromBuffer(const std::vector< uint8_t > &buffer, double hot_x, double hot_y, int width, int height)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer