- Fixed: mousepad unable to perform 2-finger right click in hovering mode

- Minor changes & improvements for mousePad widget
This commit is contained in:
TrueZhuanjia committed 2025-09-11 17:42:17 +08:00
1 parent 32b78d1a4c
commit d12b83d1ef
1 file changed
+75 -78
+75 -78
View File
@@ -195,9 +195,9 @@ import UIKit
self.touchPadString = touchPadString self.touchPadString = touchPadString
self.buttonString = self.comboButtonStrings.first ?? "" self.buttonString = self.comboButtonStrings.first ?? ""
// let stickAndMouseTouchpads = ["LSPAD", "RSPAD", "LSVPAD", "RSVPAD", "MOUSEPAD"] // let stickAndMouseTouchpads = ["LSPAD", "RSPAD", "LSVPAD", "RSVPAD", "MOUSEPAD"]
let nonVectorStickPads = ["LSPAD", "RSPAD"] let nonVectorStickPads = ["LSPAD", "RSPAD"]
// if CommandManager.touchPadCmds.contains(self.touchPadString) {self.hasSensitivityTweak = true} // if CommandManager.touchPadCmds.contains(self.touchPadString) {self.hasSensitivityTweak = true}
self.hasSensitivityTweak = CommandManager.touchPadCmds.contains(self.touchPadString) self.hasSensitivityTweak = CommandManager.touchPadCmds.contains(self.touchPadString)
// if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true} // if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true}
@@ -283,15 +283,12 @@ import UIKit
if self.widgetType == WidgetTypeEnum.button { if self.widgetType == WidgetTypeEnum.button {
self.autoTapTimer = SafeTimer(interval:0.001 * Double(autoTapInterval)) { self.autoTapTimer = SafeTimer(interval:0.001 * Double(autoTapInterval)) {
self.handleButtonDown() self.handleButtonDown()
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.main.asyncAfter(deadline: .now() + 0.025) {
usleep(25000) self.handleButtonUp()
DispatchQueue.main.async {
self.handleButtonUp()
}
}
} }
} }
} }
}
@objc public func setVibration(style: Int) { @objc public func setVibration(style: Int) {
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
@@ -312,10 +309,10 @@ import UIKit
@objc public func setLocation(position: CGPoint) { @objc public func setLocation(position: CGPoint) {
/* /*
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: xOffset), self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: xOffset),
self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: yOffset), self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: yOffset),
]) ])
*/ */
storedCenter = position storedCenter = position
center = storedCenter center = storedCenter
@@ -369,9 +366,9 @@ import UIKit
if self.heightFactor == 0 {self.heightFactor = 1.0} if self.heightFactor == 0 {self.heightFactor = 1.0}
/* /*
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: storedLocation.x), self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: storedLocation.x),
self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: storedLocation.y)]) self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: storedLocation.y)])
*/ */
@@ -391,7 +388,7 @@ import UIKit
self.backgroundColor = UIColor(white: 0.2, alpha: realBackgroundAlpha) // offset to be consistent with legacy onScreen controller layer opacity self.backgroundColor = UIColor(white: 0.2, alpha: realBackgroundAlpha) // offset to be consistent with legacy onScreen controller layer opacity
var borderAlpha = realBackgroundAlpha * 1.01 var borderAlpha = realBackgroundAlpha * 1.01
if widgetType == WidgetTypeEnum.touchPad { if widgetType == WidgetTypeEnum.touchPad {
minimumBorderAlpha = 0.0 minimumBorderAlpha = 0.0
} }
if borderAlpha < minimumBorderAlpha { if borderAlpha < minimumBorderAlpha {
borderAlpha = minimumBorderAlpha borderAlpha = minimumBorderAlpha
@@ -718,24 +715,19 @@ import UIKit
CATransaction.commit() CATransaction.commit()
CATransaction.begin() CATransaction.begin()
// CATransaction.setDisableActions(true)
CATransaction.setAnimationDuration(0.15) CATransaction.setAnimationDuration(0.15)
self.stickBallLayer.position = CGPointMake(CGRectGetMidX(self.crossMarkLayer.frame), CGRectGetMidY(self.crossMarkLayer.frame)) self.stickBallLayer.position = CGPointMake(CGRectGetMidX(self.crossMarkLayer.frame), CGRectGetMidY(self.crossMarkLayer.frame))
CATransaction.setCompletionBlock { CATransaction.setCompletionBlock {
DispatchQueue.global().async { // 动画结束后执行的代码
// 后台执行耗时操作 DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
usleep(200000) if !self.touchBegan {
DispatchQueue.main.async { // switch to main thread to update UI CATransaction.begin()
if !self.touchBegan { CATransaction.setDisableActions(true)
CATransaction.begin() self.crossMarkLayer.isHidden = true
CATransaction.setDisableActions(true) self.stickBallLayer.isHidden = true
self.crossMarkLayer.isHidden = true CATransaction.commit()
self.stickBallLayer.isHidden = true
CATransaction.commit()
}
} }
} }
// 动画结束后执行的代码
} }
CATransaction.commit() CATransaction.commit()
} }
@@ -849,8 +841,8 @@ import UIKit
if pressedButtonMask != previousButtonMask { if pressedButtonMask != previousButtonMask {
if(pressedButtonMask & Direction.up.rawValue == Direction.up.rawValue) { if(pressedButtonMask & Direction.up.rawValue == Direction.up.rawValue) {
showLrudDirectionIndicator(with: upIndicator) showLrudDirectionIndicator(with: upIndicator)
switch touchPadString { switch touchPadString {
case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_DOWN), 0) case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_DOWN), 0)
case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["UP_ARROW"]!,Int8(KEY_ACTION_DOWN), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["UP_ARROW"]!,Int8(KEY_ACTION_DOWN), 0)
case "DPAD": self.onScreenControls.pressDownControllerButton(UP_FLAG) case "DPAD": self.onScreenControls.pressDownControllerButton(UP_FLAG)
@@ -941,63 +933,62 @@ import UIKit
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
// Wait 200 ms to simulate a real button press // Wait 200 ms to simulate a real button press
usleep(UInt32(self.QUICK_TAP_TIME_INTERVAL * 1000000)) DispatchQueue.global().asyncAfter(deadline: .now() + self.QUICK_TAP_TIME_INTERVAL) {
// If quick tap is not detected, release the button
// If quick tap is not detected, release the button if !self.quickDoubleTapDetected {
if !self.quickDoubleTapDetected { LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT)
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) // NSLog("double click: first long click release")
// 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.
} }
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() { private func sendShortMouseLeftButtonClickEvent() {
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.global().asyncAfter(deadline: .now() + 0.05) {
NSLog("double click: sending short click")
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
usleep(UInt32(50 * 1000)) DispatchQueue.global().asyncAfter(deadline: .now() + 0.05) {
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT)
}
} }
} }
private func sendMouseRightButtonClickEvent() { private func sendMouseRightButtonClickEvent() {
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.global().asyncAfter(deadline: .now() + 0.05) {
usleep(UInt32(50 * 1000))
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_RIGHT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_RIGHT)
usleep(UInt32(50 * 1000)) DispatchQueue.global().asyncAfter(deadline: .now() + 0.05) {
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_RIGHT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_RIGHT)
}
} }
} }
//mousepad-trackball behavior======================================================== //mousepad-trackball behavior========================================================
private func startTrackballMomentum() { private func startTrackballMomentum() {
stopTrackballMomentum() stopTrackballMomentum()
trackballDecelerationTimer = Timer.scheduledTimer(withTimeInterval: 1/60, repeats: true) { [weak self] _ in trackballDecelerationTimer = Timer.scheduledTimer(withTimeInterval: 1/60, repeats: true) { [weak self] _ in
guard let self = self else { return } guard let self = self else { return }
LiSendMouseMoveEvent( LiSendMouseMoveEvent(
Int16(truncatingIfNeeded: Int(self.trackballVelocity.x)), Int16(truncatingIfNeeded: Int(self.trackballVelocity.x)),
Int16(truncatingIfNeeded: Int(self.trackballVelocity.y)) Int16(truncatingIfNeeded: Int(self.trackballVelocity.y))
) )
self.trackballVelocity.x *= self.trackballDecelerationRate self.trackballVelocity.x *= self.trackballDecelerationRate
self.trackballVelocity.y *= self.trackballDecelerationRate self.trackballVelocity.y *= self.trackballDecelerationRate
if abs(self.trackballVelocity.x) < self.trackballVelocityThreshold && if abs(self.trackballVelocity.x) < self.trackballVelocityThreshold &&
abs(self.trackballVelocity.y) < self.trackballVelocityThreshold { abs(self.trackballVelocity.y) < self.trackballVelocityThreshold {
self.stopTrackballMomentum() self.stopTrackballMomentum()
} }
} }
} }
private func stopTrackballMomentum() { private func stopTrackballMomentum() {
trackballDecelerationTimer?.invalidate() trackballDecelerationTimer?.invalidate()
trackballDecelerationTimer = nil trackballDecelerationTimer = nil
} }
//==== Button actions ============================================= //==== Button actions =============================================
@@ -1151,7 +1142,7 @@ import UIKit
}} }}
} }
//============================================================================== //==============================================================================
private func sendComboButtonsDownEvent(comboStrings: [String]) { private func sendComboButtonsDownEvent(comboStrings: [String]) {
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.global(qos: .userInteractive).async {
for comboString in comboStrings { for comboString in comboStrings {
@@ -1190,14 +1181,18 @@ import UIKit
} }
} }
//============================================================================== //==============================================================================
// Touch event handling // Touch event handling
private func getAllSpawnedTouchesCount(with event: UIEvent?)->Int{
return event?.allTouches?.filter({ $0.view == self }).count ?? 0
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchBegan = true self.touchBegan = true
self.firstTouchMoved = false self.firstTouchMoved = false
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
// self.isMultipleTouchEnabled = self.touchPadString == "MOUSEPAD" // only enable multi-touch in mousePad mode self.isMultipleTouchEnabled = self.widgetType == WidgetTypeEnum.button || self.touchPadString == "MOUSEPAD";
self.isMultipleTouchEnabled = self.widgetType == WidgetTypeEnum.button
if !OnScreenWidgetView.editMode && self.touchPadString == "TRACKBALL" { if !OnScreenWidgetView.editMode && self.touchPadString == "TRACKBALL" {
stopTrackballMomentum() stopTrackballMomentum()
@@ -1215,8 +1210,8 @@ import UIKit
self.latestTouchLocation = touchBeganLocation self.latestTouchLocation = touchBeganLocation
} }
let allCapturedTouchesCount = event?.allTouches?.filter({ $0.view == self }).count // this will counts all valid touches within the self widgetView, and excludes touches in other widgetViews let allSpawnedTouchesCount = self.getAllSpawnedTouchesCount(with: event) // this will counts all valid touches within the self widgetView, and excludes touches in other widgetViews
if allCapturedTouchesCount == 2 { if allSpawnedTouchesCount == 2 {
self.twoTouchesDetected = true self.twoTouchesDetected = true
} }
@@ -1244,7 +1239,7 @@ import UIKit
self.showl3r3Indicator() self.showl3r3Indicator()
self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)}
case "DPAD", "WASDPAD", "ARROWPAD": case "DPAD", "WASDPAD", "ARROWPAD":
if allCapturedTouchesCount == 1 {showLrudBall(at: touchBeganLocation)} if allSpawnedTouchesCount == 1 {showLrudBall(at: touchBeganLocation)}
if quickDoubleTapDetected { if quickDoubleTapDetected {
self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings) self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.global(qos: .userInteractive).async {
@@ -1261,7 +1256,7 @@ import UIKit
break break
} }
if self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected { if self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && allSpawnedTouchesCount == 1 && !twoTouchesDetected {
switch mouseButtonAction{ switch mouseButtonAction{
case .leftButtonDown: case .leftButtonDown:
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
@@ -1474,8 +1469,10 @@ import UIKit
switch self.touchPadString{ switch self.touchPadString{
case "MOUSEPAD": case "MOUSEPAD":
DispatchQueue.global(qos: .userInteractive).async { DispatchQueue.global(qos: .userInteractive).async {
self.updateTouchLocation(touch: touches.first!) if self.getAllSpawnedTouchesCount(with: event) == 1 {
LiSendMouseMoveEvent(Int16(truncatingIfNeeded: Int(self.deltaX * 1.7 * self.sensitivityFactorX)), Int16(truncatingIfNeeded: Int(self.deltaY * 1.7 * self.sensitivityFactorY))) self.updateTouchLocation(touch: touches.first!)
LiSendMouseMoveEvent(Int16(truncatingIfNeeded: Int(self.deltaX * 1.7 * self.sensitivityFactorX)), Int16(truncatingIfNeeded: Int(self.deltaY * 1.7 * self.sensitivityFactorY)))
}
} }
break break
case "TRACKBALL": case "TRACKBALL":
@@ -1575,7 +1572,7 @@ import UIKit
if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first
// touches.count == allCapturedTouchesCount means allfingers are lifting // touches.count == allCapturedTouchesCount means allfingers are lifting
self.sendMouseRightButtonClickEvent() if(self.mouseButtonAction == MouseButtonAction.hovering) {self.sendMouseRightButtonClickEvent()}
twoTouchesDetected = false twoTouchesDetected = false
} }