MOUSEPAD implementation

This commit is contained in:
TrueZhuangjia
2025-01-26 23:35:06 +08:00
parent 5747656be7
commit ae188fd999
3 changed files with 128 additions and 47 deletions
+1 -1
View File
@@ -74,7 +74,7 @@ import UIKit
"OSCL2" : 0,
"OSCR2" : 0]
@objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MousePAD", "DPAD", "WASDPAD", "ARROWPAD"]
@objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MOUSEPAD", "DPAD", "WASDPAD", "ARROWPAD"]
static let keyboardButtonMappings: [String: Int16] = [
// Windows Key Codes
+125 -45
View File
@@ -22,8 +22,6 @@ import UIKit
@objc static public var editMode: Bool = false
@objc static public var timestampOfButtonBeingDragged: TimeInterval = 0
private let appWindow: UIView
@objc public var keyLabel: String
@objc public var keyString: String
@objc public var timestamp: TimeInterval
@@ -32,41 +30,65 @@ import UIKit
@objc public var heightFactor: CGFloat
@objc public var backgroundAlpha: CGFloat
@objc public var latestTouchLocation: CGPoint
private let appWindow: UIView
private var touchLockedForMoveEvent: UITouch
// for LSVPAD, RSVPAD
@objc public var deltaX: CGFloat
@objc public var deltaY: CGFloat
// for LSPAD, RSPAD
@objc public var offSetX: CGFloat
@objc public var offSetY: CGFloat
// for LSVPAD, RSVPAD, LSPAD, RSPAD
private let crossMarkColor: CGColor = UIColor(white: 1, alpha: 0.7).cgColor
private let stickBallColor: CGColor = UIColor(white: 1, alpha: 0.75).cgColor
private var stickInputScale: CGFloat = 30
private var l3r3Indicator = CAShapeLayer()
private var crossMarkLayer = CAShapeLayer()
private var stickBallLayer = CAShapeLayer()
@objc public var stickIndicatorXOffset: CGFloat = 120
// check quick double tap:
private var quickDoubleTapDetected: Bool
private var touchTapTimeInterval: TimeInterval
private var touchTapTimeStamp: TimeInterval
private let QUICK_TAP_TIME_INTERVAL = 0.2
private var onScreenControls: OnScreenControls
private let label: UILabel
// private let originalBackgroundColor: UIColor
private var touchBeganLocation: CGPoint = .zero
private var storedLocation: CGPoint = .zero
private let minimumBorderAlpha: CGFloat = 0.19
private var defaultBorderColor: CGColor = UIColor(white: 0.2, alpha: 0.3).cgColor
private let moonlightPurple: CGColor = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 0.86).cgColor
private let crossMarkColor: CGColor = UIColor(white: 1, alpha: 0.7).cgColor
private let stickBallColor: CGColor = UIColor(white: 1, alpha: 0.75).cgColor
private var stickInputScale: CGFloat = 30
private let buttonDownVisualEffectLayer = CAShapeLayer()
private var buttonDownVisualEffectWidth: CGFloat
// for all LRUD pads
private var upIndicator = CAShapeLayer()
private var downIndicator = CAShapeLayer()
private var leftIndicator = CAShapeLayer()
private var rightIndicator = CAShapeLayer()
private var l3r3Indicator = CAShapeLayer()
private var crossMarkLayer = CAShapeLayer()
private var stickBallLayer = CAShapeLayer()
// for DPAD LRUD pad
private var lrudIndicatorBall = CAShapeLayer()
@objc public var stickIndicatorXOffset: CGFloat = 120
// OnScreenControls instance
private var onScreenControls: OnScreenControls
// key / button label
private let label: UILabel
// first touch location within the button or pad view (self)
private var touchBeganLocation: CGPoint = .zero
// for mousePad
private var mousePointerMoved: Bool
private var twoTouchesDetected: Bool
private var storedLocation: CGPoint = .zero // location from persisted data
private let minimumBorderAlpha: CGFloat = 0.19
private var defaultBorderColor: CGColor = UIColor(white: 0.2, alpha: 0.3).cgColor
private let moonlightPurple: CGColor = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 0.86).cgColor
// whole button press down visual effect
private let buttonDownVisualEffectLayer = CAShapeLayer()
private var buttonDownVisualEffectWidth: CGFloat
@objc init(keyString: String, keyLabel: String) {
self.keyString = keyString
@@ -89,6 +111,9 @@ import UIKit
self.touchTapTimeInterval = 100
self.touchTapTimeStamp = 100
self.buttonDownVisualEffectWidth = 0
self.mousePointerMoved = false
self.touchLockedForMoveEvent = UITouch()
self.twoTouchesDetected = false
super.init(frame: .zero)
upIndicator = createLrudDirectionLayer()
@@ -516,7 +541,44 @@ import UIKit
//================================================================================================
//===== MOUSEPAD related methods=============================================================
private func sendLongMouseLeftButtonClickEvent() {
DispatchQueue.global(qos: .userInitiated).async {
// Logging the press event
NSLog("Sending left mouse button press")
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
// Wait 200 ms to simulate a real button press
usleep(UInt32(self.QUICK_TAP_TIME_INTERVAL * 1000000))
// If quick tap is not detected, release the button
if !self.quickDoubleTapDetected {
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT)
// NSLog("double click: first long click release")
}
else{NSLog("Left mouse button release cancelled, keep pressing down, turning into dragging...")}
// Don't release the button if we're still dragging, this will prevent the dragging from being interrupted.
}
}
private func sendShortMouseLeftButtonClickEvent() {
DispatchQueue.global(qos: .userInitiated).async {
NSLog("double click: sending short click")
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT)
}
}
private func sendMouseRightButtonClickEvent() {
DispatchQueue.global(qos: .userInitiated).async {
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_RIGHT)
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_RIGHT)
}
}
//==== wholeButtonPress visual effect=============================================
private func buttonDownVisualEffect() {
@@ -592,18 +654,12 @@ import UIKit
//==========================================================================================================
// Touch event handling
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// print("touchDown: %f", CACurrentMediaTime())
if touches.count == 1 {
super.touchesBegan(touches, with: event)
self.isMultipleTouchEnabled = self.keyString == "MOUSEPAD" // only enable multi-touch in mousePad mode
if touches.count == 1 { // to make sure touchBegan location captured properly, don't use event.alltouches.count here
let currentTime = CACurrentMediaTime()
touchTapTimeInterval = currentTime - touchTapTimeStamp
touchTapTimeStamp = currentTime
@@ -613,17 +669,16 @@ import UIKit
self.touchBeganLocation = touch!.location(in: self)
self.latestTouchLocation = touchBeganLocation
}
let allCapturedTouchesCount = event?.allTouches?.filter({ $0.view == self }).count // this will counts all valid touches within the self buttonView, and excludes touches in other buttonViews
if allCapturedTouchesCount == 2 {
self.twoTouchesDetected = true
}
self.pressed = true
super.touchesBegan(touches, with: event)
//self.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 0.7)
// OnScreenControls.testMethod();
// RelativeTouchHandler.testMethod();
if !OnScreenButtonView.editMode {
if CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1{
if CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1{ // don't use event?.allTouches?.count here, it will counts all touches including the ones captured by other UIViews
switch self.keyString {
case "LSPAD":
self.showStickIndicator()
@@ -699,7 +754,7 @@ import UIKit
if !OnScreenButtonView.editMode {
if CommandManager.touchPadCmds.contains(self.keyString){
handleTouchPadMoveEvent(touches: touches)
handleTouchPadMoveEvent(touches, with: event)
}
}
@@ -718,10 +773,10 @@ import UIKit
}
private func handleTouchPadMoveEvent (touches: Set<UITouch>){
if touches.count == 1{
private func handleTouchPadMoveEvent (_ touches: Set<UITouch>, with event: UIEvent?){
if touches.count == 1{ // don't use event.alltouches.count here, it will counts all touches
self.mousePointerMoved = true
let currentTouchLocation: CGPoint = (touches.first?.location(in: self))!
self.deltaX = currentTouchLocation.x - self.latestTouchLocation.x
self.deltaY = currentTouchLocation.y - self.latestTouchLocation.y
self.offSetX = currentTouchLocation.x - self.touchBeganLocation.x
@@ -729,6 +784,9 @@ import UIKit
self.latestTouchLocation = currentTouchLocation
switch self.keyString{
case "MOUSEPAD":
LiSendMouseMoveEvent(Int16(truncatingIfNeeded: Int(deltaX)), Int16(truncatingIfNeeded: Int(deltaY)))
break
case "LSPAD":
self.sendLeftStickTouchPadEvent(inputX: offSetX, inputY: offSetY)
updateStickBallPosition()
@@ -749,10 +807,31 @@ import UIKit
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// self.pressed = false // will be reset outside the class
super.touchesEnded(touches, with: event)
quickDoubleTapDetected = false
if !OnScreenButtonView.editMode && CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1 {
if self.keyString != "MOUSEPAD" {quickDoubleTapDetected = false} //do not reset this flag here in mousePad mode
let allCapturedTouchesCount = event?.allTouches?.filter({ $0.view == self }).count // this will counts all valid touches within the self buttonView, and excludes touches in other buttonViews
// deal with MOUSPAD first
if !OnScreenButtonView.editMode && self.keyString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected {
if !mousePointerMoved && !quickDoubleTapDetected {self.sendLongMouseLeftButtonClickEvent()} // deal with single tap(click)
if quickDoubleTapDetected { //deal with quick double tap
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) //must release the button anyway, because the button is likely being held down since the long click turned into a dragging event.
if !mousePointerMoved {self.sendShortMouseLeftButtonClickEvent()}
quickDoubleTapDetected = false
}
mousePointerMoved = false // reset this flag
}
if !OnScreenButtonView.editMode && self.keyString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first
// touches.count == allCapturedTouchesCount means allfingers are lifting
self.sendMouseRightButtonClickEvent()
twoTouchesDetected = false
}
// then other types of pads
if !OnScreenButtonView.editMode && CommandManager.touchPadCmds.contains(self.keyString) {
switch self.keyString{
case "LSPAD":
self.onScreenControls.clearLeftStickTouchPadFlag()
@@ -786,6 +865,7 @@ import UIKit
}
}
self.buttonUpVisualEffect()
self.l3r3Indicator.removeFromSuperlayer()
self.upIndicator.removeFromSuperlayer()
+2 -1
View File
@@ -277,9 +277,10 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
// Wait 100 ms to simulate a real button press
usleep(QUICK_TAP_TIME_INTERVAL * 1000000);
if(!self->quickTapDetected){
NSLog(@"Left mouse button release cancelled, keep pressing down, turning into dragging...");
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
}
else NSLog(@"Left mouse button release cancelled, keep pressing down, turning into dragging...");
// do not release the button if we're still dragging, this will prevent the dragging from being interrupted.
});
}