rustdesk/flutter/lib/web/custom_cursor.dart
fufesou 3ef9824d8e
Flutter web, custom cursor (#7545)
* 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>
2024-03-29 10:52:32 +08:00

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);
}
}