- feat: auto tap for on-screen widget.

- fixed: on-screen widget button stuck.
This commit is contained in:
TrueZhuanjia committed 2025-09-10 03:02:28 +08:00
1 parent d818f8a7ce
commit 4e65abf6b1
16 files changed
+628 -234

No files matched your search

+82 -18
View File
@@ -31,6 +31,8 @@ import UIKit
case touchPad
}
@objc static public var tapGestureShallBeCancelled: Bool = false
@objc public var widgetType: WidgetTypeEnum = WidgetTypeEnum.uninitialized
@objc static public var editMode: Bool = false
@@ -61,6 +63,10 @@ import UIKit
@objc public var layoutChanges: [CGPoint] = []
@objc public var mouseButtonAction: MouseButtonAction = .hovering;
//autoTapTimer
@objc public var autoTapInterval: Int = 49;
private var autoTapTimer: SafeTimer?
private let appWindow: UIView
private var vibrationGenerator = UIImpactFeedbackGenerator(style: .light)
@@ -150,6 +156,7 @@ import UIKit
//slide buttons
private var capturedTouches: NSMutableSet
private let noTouch: UITouch = UITouch()
let setLock = NSLock()
//controller touch pad
private var pointerIdPool: Set<UInt32>
@@ -266,7 +273,6 @@ import UIKit
rightIndicator.anchorPoint = CGPoint(x: 0, y: 0.5)
setupView()
}
required init?(coder: NSCoder) {
@@ -274,6 +280,19 @@ import UIKit
}
// ======================================================================================================
@objc public func setupAutoTapTimer() {
if self.widgetType == WidgetTypeEnum.button {
self.autoTapTimer = SafeTimer(interval:0.001 * Double(autoTapInterval)) {
self.handleButtonDown()
DispatchQueue.global(qos: .userInteractive).async {
usleep(25000)
DispatchQueue.main.async {
self.handleButtonUp()
}
}
}
}
}
@objc public func setVibration(style: Int) {
if #available(iOS 13.0, *) {
@@ -980,7 +999,28 @@ import UIKit
}
//==== wholeButtonPress visual effect=============================================
//==== Button actions =============================================
//==== Button widget tap down=============================================
private func handleTapDownOrSlidein() {
if autoTapInterval < 50 {
handleButtonDown()
}
else{
self.autoTapTimer?.restart()
}
}
private func handleFingerUpOrSlideout() {
if autoTapInterval < 50 {
handleButtonUp()
}
else{
self.autoTapTimer?.suspend()
self.handleButtonUp()
}
}
private func handleButtonDown() {
if !OnScreenWidgetView.editMode {self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)}
CATransaction.begin()
@@ -997,7 +1037,7 @@ import UIKit
CATransaction.commit()
}
private func handlebuttonUp() {
private func handleButtonUp() {
if !OnScreenWidgetView.editMode {self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings)}
CATransaction.begin()
CATransaction.setDisableActions(true)
@@ -1150,6 +1190,7 @@ import UIKit
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchBegan = true
self.firstTouchMoved = false
OnScreenWidgetView.tapGestureShallBeCancelled = true
super.touchesBegan(touches, with: event)
// self.isMultipleTouchEnabled = self.touchPadString == "MOUSEPAD" // only enable multi-touch in mousePad mode
self.isMultipleTouchEnabled = self.widgetType == WidgetTypeEnum.button
@@ -1238,8 +1279,10 @@ import UIKit
// this will also deal with button events
if self.widgetType == WidgetTypeEnum.button && !self.comboButtonStrings.isEmpty {
self.handleButtonDown()
self.handleTapDownOrSlidein()
setLock.lock()
self.capturedTouches.union(touches)
setLock.unlock()
//self.handleButtonSliding(touches: touches)
}
@@ -1248,7 +1291,7 @@ import UIKit
let keyboardCmdStrings = CommandManager.shared.extractKeyStringsFromComboCommand(from: self.cmdString)!
CommandManager.shared.sendKeyComboCommand(keyboardCmdStrings: keyboardCmdStrings) // send multi-key command
DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { // reset shadow color immediately 50ms later
self.handlebuttonUp()
self.handleButtonUp()
}
}
}
@@ -1316,12 +1359,18 @@ import UIKit
}
private func handleButtonSlidingUp(touches: Set<UITouch>) {
private func handleFingerUpAfterSliding(touches: Set<UITouch>) {
for touch in touches {
for subview in self.superview?.subviews ?? [] {
if let widget = subview as? OnScreenWidgetView{
if !widget.capturedTouches.contains(touch) || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
widget.handlebuttonUp()
setLock.lock()
let captured = widget.capturedTouches.contains(touch)
setLock.unlock()
if !captured || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
widget.handleFingerUpOrSlideout()
setLock.lock()
widget.capturedTouches.remove(touch)
setLock.unlock()
}
}
}
@@ -1335,17 +1384,27 @@ import UIKit
if widget.widgetType != WidgetTypeEnum.button {continue}
let pointInSubview = widget.convert(locationInSuperView, from: self.superview)
if widget.bounds.contains(pointInSubview){
if widget.capturedTouches.contains(touch) || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
setLock.lock()
let captured = widget.capturedTouches.contains(touch)
setLock.unlock()
if captured || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
setLock.lock()
widget.capturedTouches.add(touch)
widget.handleButtonDown()
setLock.unlock()
widget.handleTapDownOrSlidein()
// print("UIButton: \(widget.buttonLabel) in, \(widget.touchPadString), \(CACurrentMediaTime())")
}
else{
if !widget.capturedTouches.contains(touch) || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
setLock.lock()
let captured = widget.capturedTouches.contains(touch)
setLock.unlock()
if !captured || widget.slideMode == ButtonSlideMode.disabled.rawValue {continue}
// print("UIButton: \(widget.buttonLabel) out test, \(widget.touchPadString), \(CACurrentMediaTime())")
if(widget.slideMode == ButtonSlideMode.toggle.rawValue){
widget.handleFingerUpOrSlideout()
setLock.lock()
widget.capturedTouches.remove(touch)
widget.handlebuttonUp()
setLock.unlock()
}
if(widget.slideMode == ButtonSlideMode.slideAndHold.rawValue){
// do nothing here
@@ -1364,7 +1423,7 @@ import UIKit
handleTouchPadMoveEvent(touches, with: event)
}
if !self.buttonString.isEmpty{
if self.widgetType == WidgetTypeEnum.button {
if self.slideMode != ButtonSlideMode.disabled.rawValue {self.handleButtonSliding(touches: touches)}
}
@@ -1373,7 +1432,7 @@ import UIKit
NSLog("touchTapTimeStamp %f", self.touchTapTimeStamp)
if CACurrentMediaTime() - self.touchTapTimeStamp > 0.3 { // temporarily relocate special buttons
self.moveByTouch(touch: touch)
self.handlebuttonUp()
self.handleButtonUp()
}
}
}
@@ -1457,10 +1516,14 @@ import UIKit
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
touchesEnded(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchBegan = false
super.touchesEnded(touches, with: event)
CATransaction.begin()
CATransaction.setDisableActions(true)
@@ -1560,8 +1623,10 @@ import UIKit
}
if !OnScreenWidgetView.editMode && !self.cmdString.contains("+") && !self.comboButtonStrings.isEmpty { // if the command(keystring contains "+", it's a legacy multi-key command
self.handleButtonSlidingUp(touches: touches)
self.handleFingerUpAfterSliding(touches: touches)
setLock.lock()
self.capturedTouches.minus(touches)
setLock.unlock()
}
if !OnScreenWidgetView.editMode && CommandManager.specialOverlayButtonCmds.contains(self.cmdString){
@@ -1613,8 +1678,7 @@ import UIKit
}
}
self.handlebuttonUp()
self.handleFingerUpOrSlideout()
}
}