diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index ed94cd3f..6a316f55 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -400,6 +400,7 @@ import ObjectiveC.runtime @objc private(set) var firstTouchMoved: Bool = false private var mousePointerMoved: Bool private var twoTouchesDetected: Bool + private var scrollEventSent: Bool = false private var allSpawnedTouchesCount: Int = 0 // trackball @@ -681,6 +682,10 @@ import ObjectiveC.runtime self.isMagnifier = self.cmdString.contains("MAGNIFIER") self.hasAnchorMode = isDisplacementBasedStickPad || isDirectionPad + + self.isMultipleTouchEnabled = self.widgetType == WidgetTypeEnum.button + || CommandManager.mousePadWithButtonActions.contains(self.touchPadString) + || self.touchPadString == "MAGNIFIER" } // ====================================================================================================== @@ -1062,7 +1067,7 @@ import ObjectiveC.runtime } let attr = NSAttributedString( - string: self.folded ? "[\(text)]" : (self.isFolder ? " 🟡 \(text)" : "\(text)"), + string: (self.isFolder && self.folded) ? "[\(text)]" : (self.isFolder ? " 🟡 \(text)" : "\(text)"), attributes: [ .foregroundColor: UIColor(white:labelAlpha>0 ? 1.0 : 0, alpha: abs(labelAlpha)), // 填充色 .strokeColor: (labelAlpha>0 ? UIColor.black : UIColor.white).withAlphaComponent(abs(labelAlpha)*0.43), // 描边色 @@ -2060,14 +2065,11 @@ import ObjectiveC.runtime self.touchBegan = true self.directionPadTouchBegan = true self.firstTouchMoved = false + self.scrollEventSent = false self.tickFlag = 0 // super.touchesBegan(touches, with: event) if OnScreenWidgetView.editMode {self.parentViewController?.touchesBegan(touches, with: event)} - self.isMultipleTouchEnabled = self.widgetType == WidgetTypeEnum.button - || CommandManager.mousePadWithButtonActions.contains(self.touchPadString) - || self.touchPadString == "MAGNIFIER" - if !OnScreenWidgetView.editMode && self.touchPadString == "TRACKBALL" { stopTrackballMomentum() } @@ -2553,14 +2555,15 @@ import ObjectiveC.runtime private func handleTouchPadMoveEvent (_ touches: Set, with event: UIEvent?){ guard let touch = touches.first else { return } - if touches.count == 1{ // don't use event.alltouches.count here, it will counts all touches + let activeTouchesCount = UITouchUtil.touches(in: self, from: event).count + if activeTouchesCount == 1 { // don't use event.alltouches.count here, it will counts all touches self.getVector(touch: touch) switch self.touchPadString{ case "MOUSEPAD": DispatchQueue.global(qos: .userInteractive).async { self.weightedDeltaX = Int(self.deltaX * 1.7 * self.sensitivityFactorX) self.weightedDeltaY = Int(self.deltaY * 1.7 * self.sensitivityFactorY) - if self.firstTouchMoved {LiSendMouseMoveEvent(Int16(self.weightedDeltaX), Int16(self.weightedDeltaY))} + if self.firstTouchMoved, !self.scrollEventSent {LiSendMouseMoveEvent(Int16(self.weightedDeltaX), Int16(self.weightedDeltaY))} self.updateTouchLocation(touch: touch) } break @@ -2672,6 +2675,25 @@ import ObjectiveC.runtime break } } + if activeTouchesCount == 2 { + self.getVector(touch: touch) + switch self.touchPadString{ + case "MOUSEPAD": + if self.mouseButtonAction == .hovering, firstTouchMoved { + mousePointerMoved = false + let touchesArr = Array(touches) + let vector = UITouchUtil.midPointVector(between: touchesArr.first, and: touchesArr.last, in: self) + self.scrollEventSent = true + if abs(vector.dx) > 1.2*abs(vector.dy) { + LiSendHighResHScrollEvent(-Int16(vector.dx*5)) + } + else { + LiSendHighResScrollEvent(Int16(vector.dy*5)) + } + } + default: break + } + } if self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "DS4TOUCH" { self.handleControllerTouchesMove(touches: touches) } @@ -3029,12 +3051,15 @@ import ObjectiveC.runtime if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && CommandManager.mousePadWithButtonActions.contains(self.touchPadString) && allSpawnedTouchesCount == 1 && !twoTouchesDetected { self.handleMousePadButtonActionUp() } - if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && CommandManager.mousePadWithButtonActions.contains(self.touchPadString) && twoTouchesDetected && touches.count == allSpawnedTouchesCount { // need to enable multi-touch first // touches.count == allCapturedTouchesCount means allfingers are lifting - if(self.mouseButtonAction == MouseButtonAction.hovering) {self.sendMouseRightButtonClickEvent()} - twoTouchesDetected = false + if self.mouseButtonAction == MouseButtonAction.hovering, !scrollEventSent {self.sendMouseRightButtonClickEvent()} + } + if touches.count == allSpawnedTouchesCount { firstTouchMoved = false + twoTouchesDetected = false + scrollEventSent = false + twoTouchesDetected = false } // then other types of pads or buttons with touchPad function @@ -3279,10 +3304,12 @@ import ObjectiveC.runtime if OnScreenWidgetView.capturer == nil, OnScreenWidgetView.editMode { if OnScreenWidgetView.isVerticallyAligned { self.center = CGPoint(x:OnScreenWidgetView.alignedX, y:self.center.y) + self.storedCenter = self.center OnScreenWidgetView.isVerticallyAligned = false } if OnScreenWidgetView.isHorizontallyAligned { self.center = CGPoint(x:self.center.x, y:OnScreenWidgetView.alignedY) + self.storedCenter = self.center OnScreenWidgetView.isHorizontallyAligned = false } } diff --git a/VoidLink/Input/TouchPadGestureHandler.swift b/VoidLink/Input/TouchPadGestureHandler.swift index 4f64fe76..b683dfac 100644 --- a/VoidLink/Input/TouchPadGestureHandler.swift +++ b/VoidLink/Input/TouchPadGestureHandler.swift @@ -49,12 +49,14 @@ import UIKit let midPointDeltaX = midPointVector.dx let midPointDeltaY = midPointVector.dy - inertialScroller.vector = CGVector(dx: midPointDeltaX, dy: midPointDeltaY) + let sendHorizontalScroll = abs(midPointDeltaX) > 1.2*abs(midPointDeltaY) + + inertialScroller.vector = CGVector(dx: sendHorizontalScroll ? midPointDeltaX : 0, dy: midPointDeltaY) let originalPinchDelta = currentDistance-previousDistance; let pinchDelta = enablePinch ? originalPinchDelta*7*pinchSensitivity : 0; LiSendHighResScrollEvent(Int16(pinchDelta + midPointDeltaY*7*scrollSensitivity)) - if enableHorizontalScroll {LiSendHighResHScrollEvent(Int16(-midPointDeltaX*7*scrollSensitivity))} + if enableHorizontalScroll, sendHorizontalScroll {LiSendHighResHScrollEvent(Int16(-midPointDeltaX*7*scrollSensitivity))} if enablePinch, ctrlDownForPinch { let midPointDelta = hypot(midPointDeltaX, midPointDeltaY) diff --git a/VoidLink/Input/UITouchUtil.swift b/VoidLink/Input/UITouchUtil.swift index 086a334c..9ca81593 100644 --- a/VoidLink/Input/UITouchUtil.swift +++ b/VoidLink/Input/UITouchUtil.swift @@ -10,8 +10,10 @@ import UIKit @objc class UITouchUtil: NSObject { @objc public static func touches(in view: UIView, from event: UIEvent?) -> Set { - guard (event?.allTouches) != nil else { return [] } - return event?.allTouches?.filter({ $0.view == view && ($0.type == .direct || $0.type == .pencil)}) ?? [] + guard let touches = event?.allTouches else { return [] } + return touches.filter { + $0.view === view && ($0.type == .direct || $0.type == .pencil) + } } @objc public static func distance(between touch1: UITouch?, and touch2: UITouch?, in view: UIView?) -> CGFloat { diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index d9c0ba50..c5ddebb2 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1220,7 +1220,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Enter PiP" + "value" : "PiP" } }, "zh-Hans" : { @@ -1231,13 +1231,13 @@ }, "zh-Hant" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "子母畫面" } }, "zh-HK" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "子母畫面" } } @@ -1382,7 +1382,7 @@ }, "zh-HK" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "控制項夾" } } @@ -11839,7 +11839,7 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/nm6l9yixu0idsybg#32535f99" } }, @@ -12120,6 +12120,64 @@ } } }, + "pipDisabled" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please enable Picture in Picture in both System Settings and the app settings." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请在系统设置与 App 设置中启用画中画" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "請在系統設定與 App 設定中啟用子母畫面。" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "請在系統設定與 App 設定中啟用子母畫面。" + } + } + } + }, + "pipNotSupported" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Picture in Picture is not supported by the system." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "系统不支持画中画。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "系統不支援子母畫面。" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "系統不支援子母畫面。" + } + } + } + }, "pipStackTip" : { "extractionState" : "manual", "localizations" : { diff --git a/VoidLink/PresetConfigs/widgetTemplates.bin b/VoidLink/PresetConfigs/widgetTemplates.bin index 90d34067..fd4f3402 100644 Binary files a/VoidLink/PresetConfigs/widgetTemplates.bin and b/VoidLink/PresetConfigs/widgetTemplates.bin differ diff --git a/VoidLink/PresetConfigs/widgetTemplatesIPhone.bin b/VoidLink/PresetConfigs/widgetTemplatesIPhone.bin index 663b4c83..2fbdae73 100644 Binary files a/VoidLink/PresetConfigs/widgetTemplatesIPhone.bin and b/VoidLink/PresetConfigs/widgetTemplatesIPhone.bin differ diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift index efd6e33a..343bd460 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift @@ -1252,7 +1252,6 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg newWidget.sequence = widget.sequence newWidget.autoDockIdleDuration = widget.autoDockIdleDuration newWidget.autoDockSettledAlpha = widget.autoDockSettledAlpha - newWidget.folded = widget.folded newWidget.revealMode = widget.revealMode newWidget.bulkMoveEnabled = widget.bulkMoveEnabled newWidget.layoutUpdateDelegate = self @@ -1283,6 +1282,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg guard newWidget.widgetType == widget.widgetType else { return } view.insertSubview(newWidget, belowSubview: widgetPanelStack) newWidget.accessWidgetAttributes() + newWidget.folded = newWidget.isFolder && widget.folded newWidget.buttonMode = (newWidget.widgetType == .button && newWidget.touchPadString != "") ? .regular : widget.buttonMode newWidget.sensitivityFactorX = widget.sensitivityFactorX newWidget.componentSizeFactor = widget.componentSizeFactor @@ -1304,7 +1304,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg newWidget.adjustTransparency(alpha: widget.originalBackgroundAlpha, tweakBorderAlpha: false) newWidget.tweakLabelAlpha(alpha: widget.originalLabelAlpha) - if widget.isFolder {newWidget.reverseColorPhase(reversed: !newWidget.folded)} + if newWidget.isFolder {newWidget.reverseColorPhase(reversed: !newWidget.folded)} newWidget.tweakBorderAlpha(alpha: widget.borderAlpha) newWidget.tweakHighlightAlpha(alpha: widget.highlightAlpha) diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index e224d0ea..fb7b30ac 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -1057,6 +1057,30 @@ static NSString* VLTerminationHintForErrorCode(int errorCode) { } - (void)enterPip{ + if (@available(iOS 15.0, tvOS 15.0, *)) { + if(!_settings.enablePIP){ + AlertControllerUtil.autoCompletion = true; + [AlertControllerUtil showAlertIn:self + title:@"" + message:[LocalizationHelper localizedStringForKey:@"pipDisabled"] + withCancel:NO + buttonTitle:@"" + countdown:1 + action:^{} + completion:^{}]; + } + } + else { + AlertControllerUtil.autoCompletion = true; + [AlertControllerUtil showAlertIn:self + title:@"" + message:[LocalizationHelper localizedStringForKey:@"pipNotSupported"] + withCancel:NO + buttonTitle:@"" + countdown:1 + action:^{} + completion:^{}]; + } [self.pipController startPictureInPicture]; } diff --git a/VoidLinkPreview/WidgetPickerView.swift b/VoidLinkPreview/WidgetPickerView.swift index f5be7efd..bea04015 100644 --- a/VoidLinkPreview/WidgetPickerView.swift +++ b/VoidLinkPreview/WidgetPickerView.swift @@ -3280,7 +3280,8 @@ struct WidgetPickerView: View { } private var comboJoiner: String { - (isShortcutPickerMode || effectiveWidgetComboMode == .shortcut) ? "+" : "-" + (isShortcutPickerMode || effectiveWidgetComboMode == .shortcut) + && selectedFunctionalButtonOption?.allowsShortcutCombo != false ? "+" : "-" } private func setCreateWidgetSheetVisible(_ isVisible: Bool) {