mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
92 lines
3.6 KiB
Dart
92 lines
3.6 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:accessibility/accessibility.dart';
|
|
import 'package:bluetooth_low_energy/bluetooth_low_energy.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:swift_control/bluetooth/devices/zwift/zwift_click.dart';
|
|
import 'package:swift_control/main.dart';
|
|
import 'package:swift_control/utils/actions/base_actions.dart';
|
|
import 'package:swift_control/utils/keymap/buttons.dart';
|
|
import 'package:swift_control/utils/keymap/keymap.dart';
|
|
import 'package:swift_control/widgets/keymap_explanation.dart';
|
|
import 'package:universal_ble/universal_ble.dart';
|
|
|
|
import '../requirements/remote.dart';
|
|
|
|
class RemoteActions extends BaseActions {
|
|
RemoteActions({super.supportedModes = const [SupportedMode.touch]});
|
|
|
|
@override
|
|
Future<ActionResult> performAction(ControllerButton action, {bool isKeyDown = true, bool isKeyUp = false}) async {
|
|
if (supportedApp == null) {
|
|
return Error('Supported app is not set');
|
|
}
|
|
|
|
final keyPair = supportedApp!.keymap.getKeyPair(action);
|
|
if (keyPair == null) {
|
|
return Error('Keymap entry not found for action: ${action.toString().splitByUpperCase()}');
|
|
} else if (keyPair.hasNoAction) {
|
|
return Error('No action assigned for ${action.toString().splitByUpperCase()}');
|
|
}
|
|
|
|
final directConnectHandled = await handleDirectConnect(keyPair);
|
|
|
|
if (directConnectHandled != null) {
|
|
return directConnectHandled;
|
|
} else if (!(actionHandler as RemoteActions).isConnected) {
|
|
return Error('Not connected to a ${settings.getLastTarget()?.name ?? 'remote'} device');
|
|
}
|
|
|
|
if (keyPair.physicalKey != null && keyPair.touchPosition == Offset.zero) {
|
|
return Error('Physical key actions are not supported, yet');
|
|
} else {
|
|
final point = await resolveTouchPosition(keyPair: keyPair, windowInfo: null);
|
|
final point2 = point; //Offset(100, 99.0);
|
|
await sendAbsMouseReport(0, point2.dx.toInt(), point2.dy.toInt());
|
|
await sendAbsMouseReport(1, point2.dx.toInt(), point2.dy.toInt());
|
|
await sendAbsMouseReport(0, point2.dx.toInt(), point2.dy.toInt());
|
|
|
|
return Success('Mouse clicked at: ${point2.dx.toInt()} ${point2.dy.toInt()}');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<Offset> resolveTouchPosition({required KeyPair keyPair, required WindowEvent? windowInfo}) async {
|
|
// for remote actions we use the relative position only
|
|
return keyPair.touchPosition;
|
|
}
|
|
|
|
Uint8List absMouseReport(int buttons3bit, int x, int y) {
|
|
final b = buttons3bit & 0x07;
|
|
final xi = x.clamp(0, 100);
|
|
final yi = y.clamp(0, 100);
|
|
return Uint8List.fromList([b, xi, yi]);
|
|
}
|
|
|
|
// Send a relative mouse move + button state as 3-byte report: [buttons, dx, dy]
|
|
Future<void> sendAbsMouseReport(int buttons, int dx, int dy) async {
|
|
final bytes = absMouseReport(buttons, dx, dy);
|
|
if (kDebugMode) {
|
|
print('Preparing to send abs mouse report: buttons=$buttons, dx=$dx, dy=$dy');
|
|
print('Sending abs mouse report: ${bytes.map((e) => e.toRadixString(16).padLeft(2, '0'))}');
|
|
}
|
|
|
|
await peripheralManager.notifyCharacteristic(connectedCentral!, connectedCharacteristic!, value: bytes);
|
|
|
|
// we don't want to overwhelm the target device
|
|
await Future.delayed(Duration(milliseconds: 10));
|
|
}
|
|
|
|
Central? connectedCentral;
|
|
GATTCharacteristic? connectedCharacteristic;
|
|
|
|
void setConnectedCentral(Central? central, GATTCharacteristic? gattCharacteristic) {
|
|
connectedCentral = central;
|
|
connectedCharacteristic = gattCharacteristic;
|
|
|
|
connection.signalChange(ZwiftClick(BleDevice(deviceId: 'deviceId', name: 'name')));
|
|
}
|
|
|
|
bool get isConnected => connectedCentral != null;
|
|
}
|