import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:core';
import 'dart:ui'; 

class MouseCursorPainter extends CustomPainter {
  MouseCursorPainter({required this.offset, this.factor = 64.0});

  final Offset offset;
  final double factor;

  @override
  void paint(Canvas canvas, Size size) {
    final path = Path()
      ..moveTo(offset.dx, offset.dy)
      ..lineTo(offset.dx, offset.dy + 48 * factor / 64)
      ..lineTo(offset.dx + 34 * factor / 64, offset.dy + 34 * factor / 64)
      ..close();

    canvas.drawPath(
      path,
      Paint()
        ..color = Colors.black
        ..style = PaintingStyle.fill,
    );

    canvas.drawPath(
      path,
      Paint()
        ..color = Colors.white
        ..style = PaintingStyle.stroke
        ..strokeJoin = StrokeJoin.miter
        ..strokeWidth = 3.5 * factor / 64,
    );
  }

  @override
  bool shouldRepaint(covariant MouseCursorPainter oldDelegate) {
    return oldDelegate.offset != offset;
  }
}

class SoftwareMouseCursor extends StatelessWidget {
  SoftwareMouseCursor({Key? key, required this.child}) : super(key: key);

  final cursorPos = ValueNotifier(Offset.zero);
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (event) {
        if (event.kind == PointerDeviceKind.mouse) {
          cursorPos.value = event.position;
        }
      },
      onPointerMove: (event) {
        if (event.kind == PointerDeviceKind.mouse) {
          cursorPos.value = event.position;
        }
      },
      onPointerUp: (event) {
        if (event.kind == PointerDeviceKind.mouse) {
          cursorPos.value = event.position;
        }
      },
      onPointerHover: (event) {
        if (event.kind == PointerDeviceKind.mouse) {
          cursorPos.value = event.position;
        }
      },
      behavior: HitTestBehavior.translucent,
      child: ValueListenableBuilder<Offset>(
        valueListenable: cursorPos,
        builder: (context, pos, child) {
          return CustomPaint(
            foregroundPainter: MouseCursorPainter(
              offset: pos,
              factor: window.devicePixelRatio * 64,
            ),
            child: child,
          );
        },
        child: RepaintBoundary(
          child: child,
        ),
      ),
    );
  }
}
