* Flutter web, custom cursor Signed-off-by: fufesou <shuanglongchen@yeah.net> * trivial changes Signed-off-by: fufesou <shuanglongchen@yeah.net> * Flutter web, custom cursor, use date after 'updateGetKey()' Signed-off-by: fufesou <shuanglongchen@yeah.net> * trivial changes Signed-off-by: fufesou <shuanglongchen@yeah.net> --------- Signed-off-by: fufesou <shuanglongchen@yeah.net>
		
			
				
	
	
		
			122 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'dart:convert';
 | |
| import 'dart:js' as js;
 | |
| 
 | |
| import 'package:flutter/foundation.dart';
 | |
| import 'package:flutter/services.dart';
 | |
| 
 | |
| import 'package:flutter_hbb/models/model.dart' as model;
 | |
| 
 | |
| class CursorData {
 | |
|   final String key;
 | |
|   final String url;
 | |
|   final double hotX;
 | |
|   final double hotY;
 | |
|   final int width;
 | |
|   final int height;
 | |
| 
 | |
|   CursorData({
 | |
|     required this.key,
 | |
|     required this.url,
 | |
|     required this.hotX,
 | |
|     required this.hotY,
 | |
|     required this.width,
 | |
|     required this.height,
 | |
|   });
 | |
| }
 | |
| 
 | |
| /// The cursor manager
 | |
| class CursorManager {
 | |
|   final Map<String, CursorData> _cursors = <String, CursorData>{};
 | |
|   String latestKey = '';
 | |
| 
 | |
|   CursorManager._();
 | |
|   static CursorManager instance = CursorManager._();
 | |
| 
 | |
|   Future<void> registerCursor(CursorData data) async {
 | |
|     _cursors[data.key] = data;
 | |
|   }
 | |
| 
 | |
|   Future<void> deleteCursor(String key) async {
 | |
|     _cursors.remove(key);
 | |
|   }
 | |
| 
 | |
|   Future<void> setSystemCursor(String key) async {
 | |
|     if (latestKey == key) {
 | |
|       return;
 | |
|     }
 | |
|     latestKey = key;
 | |
| 
 | |
|     final CursorData? cursorData = _cursors[key];
 | |
|     if (cursorData != null) {
 | |
|       js.context.callMethod('setByName', [
 | |
|         'cursor',
 | |
|         jsonEncode({
 | |
|           'url': cursorData.url,
 | |
|           'hotx': cursorData.hotX.toInt(),
 | |
|           'hoty': cursorData.hotY.toInt(),
 | |
|         })
 | |
|       ]);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class FlutterCustomMemoryImageCursor extends MouseCursor {
 | |
|   final String key;
 | |
|   const FlutterCustomMemoryImageCursor({required this.key});
 | |
| 
 | |
|   @override
 | |
|   MouseCursorSession createSession(int device) =>
 | |
|       _FlutterCustomMemoryImageCursorSession(this, device);
 | |
| 
 | |
|   @override
 | |
|   String get debugDescription =>
 | |
|       objectRuntimeType(this, 'FlutterCustomMemoryImageCursor');
 | |
| }
 | |
| 
 | |
| class _FlutterCustomMemoryImageCursorSession extends MouseCursorSession {
 | |
|   _FlutterCustomMemoryImageCursorSession(
 | |
|       FlutterCustomMemoryImageCursor cursor, int device)
 | |
|       : super(cursor, device);
 | |
| 
 | |
|   @override
 | |
|   FlutterCustomMemoryImageCursor get cursor =>
 | |
|       super.cursor as FlutterCustomMemoryImageCursor;
 | |
| 
 | |
|   @override
 | |
|   Future<void> activate() async {
 | |
|     await CursorManager.instance.setSystemCursor(cursor.key);
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void dispose() {}
 | |
| }
 | |
| 
 | |
| deleteCustomCursor(String key) => CursorManager.instance.deleteCursor(key);
 | |
| 
 | |
| MouseCursor buildCursorOfCache(
 | |
|     model.CursorModel cursor, double scale, model.CursorData? cache) {
 | |
|   if (cache == null) {
 | |
|     return MouseCursor.defer;
 | |
|   } else {
 | |
|     final key = cache.updateGetKey(scale);
 | |
|     if (!cursor.cachedKeys.contains(key)) {
 | |
|       // data should be checked here, because it may be changed after `updateGetKey()`
 | |
|       final data = cache.data;
 | |
|       if (data == null) {
 | |
|         return MouseCursor.defer;
 | |
|       }
 | |
|       debugPrint(
 | |
|           "Register custom cursor with key $key (${cache.hotx},${cache.hoty})");
 | |
|       CursorManager.instance.registerCursor(CursorData(
 | |
|           key: key,
 | |
|           url: 'data:image/rgba;base64,${base64Encode(data)}',
 | |
|           width: (cache.width * cache.scale).toInt(),
 | |
|           height: (cache.height * cache.scale).toInt(),
 | |
|           hotX: cache.hotx,
 | |
|           hotY: cache.hoty));
 | |
|       cursor.addKey(key);
 | |
|     }
 | |
|     return FlutterCustomMemoryImageCursor(key: key);
 | |
|   }
 | |
| }
 |