From 511e7c0e4bc17f6eb7d5557495ab7f84ea522201 Mon Sep 17 00:00:00 2001 From: True Zhuanjia Date: Sat, 30 May 2026 17:42:15 +0800 Subject: [PATCH] folder widget & autodock improvement and fixes --- VoidLink/Input/ControllerSupport.m | 6 ++++++ VoidLink/Input/OnScreenWidgetView.swift | 18 +++++++++++++----- VoidLink/Input/StreamView.m | 7 +++++-- VoidLink/Localization/Localizable.xcstrings | 10 +++++----- .../LayoutOnScreenControlsViewController.swift | 10 ++++++++++ 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/VoidLink/Input/ControllerSupport.m b/VoidLink/Input/ControllerSupport.m index 16124c0f..ad5622ce 100644 --- a/VoidLink/Input/ControllerSupport.m +++ b/VoidLink/Input/ControllerSupport.m @@ -773,6 +773,12 @@ static const double MOUSE_SPEED_DIVISOR = 1.25; return YES; } + for(OnScreenWidgetView* widget in OnScreenWidgetView.mapping.allValues) { + if(widget.isFolder && widget.parentSequence<0 && widget.autoDockIdleDuration>0) { + [widget restartAutoDockCountdown]; + } + } + uint8_t type = LI_CTYPE_UNKNOWN; uint16_t capabilities = 0; uint32_t supportedButtonFlags = 0; diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index 32e14134..a349af4f 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -446,7 +446,8 @@ import ObjectiveC.runtime @objc public var standardFoldingInterval: TimeInterval = 0.05 static weak var capturer: OnScreenWidgetView? @objc static weak var deepestButton: OnScreenWidgetView? - + @objc static var autoDockEnabledFolders: Set? + @objc init(cmdString: String, buttonLabel: String, shape:String, profile:OSCProfile) { self.cmdString = cmdString @@ -2413,11 +2414,12 @@ import ObjectiveC.runtime for widget in OnScreenWidgetView.mapping.values { let parentFolder = OnScreenWidgetView.mapping[widget.parentSequence] if widget.widgetType != WidgetTypeEnum.button {continue} - let isSlidableButton = (widget.buttonMode == .slideToToggle + var isSlidableButton = (widget.buttonMode == .slideToToggle || widget.buttonMode == .slideAndHold || (widget.buttonMode == .movable && widget != self) || (widget.buttonMode == .regular && parentFolder?.isFolder == true && parentFolder?.buttonMode == .slideAndHold) ) + isSlidableButton = isSlidableButton && !widget.autoDockIsDocked if isLocation(locationInSuperView, in: widget){ setLock.lock() let captured = widget.capturedTouches.contains(touch) @@ -3380,7 +3382,7 @@ import ObjectiveC.runtime } // MARK: - Auto Dock - private static let autoDockExposedEdgeLength: CGFloat = GenericUtils.isIPhone() ? 90 : 90 + private static let autoDockExposedEdgeLength: CGFloat = GenericUtils.isIPhone() ? 70 : 90 private static let autoDockExposedThickness: CGFloat = 22 private static let autoDockVerticalInset: CGFloat = 12 @objc var autoDockIdleDuration: TimeInterval = 0 @@ -3470,7 +3472,7 @@ import ObjectiveC.runtime autoDockEnabled = enabled if enabled { OnScreenWidgetView.installAutoDockIfNeeded() - autoDockRestartCountdownIfNeeded() + // autoDockRestartCountdownIfNeeded() } else { autoDockStopCountdown() @@ -3586,6 +3588,12 @@ import ObjectiveC.runtime // if hasUnfoldedSubfolders() {return} self.isUserInteractionEnabled = false + + if let deepstButton = OnScreenWidgetView.deepestButton { + self.superview?.insertSubview(self, belowSubview: deepstButton) + OnScreenWidgetView.deepestButton = self + } + guard let hostView = superview, !OnScreenWidgetView.editMode, autoDockEnabled, @@ -4064,7 +4072,7 @@ import ObjectiveC.runtime else{ self.superViewWidth = (superview?.bounds.size.width)! self.superViewHeight = (superview?.bounds.size.height)! - autoDockRestartCountdownIfNeeded() + // autoDockRestartCountdownIfNeeded() } } diff --git a/VoidLink/Input/StreamView.m b/VoidLink/Input/StreamView.m index 5293df73..bfd70951 100644 --- a/VoidLink/Input/StreamView.m +++ b/VoidLink/Input/StreamView.m @@ -782,8 +782,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; [widgetView setupAtrributedText]; - if(widgetView.isFolder && widgetView.parentSequence<0 && widgetView.autoDockIdleDuration>0) [widgetView setAutoDockWithEnabled:true]; - + if(widgetView.isFolder && widgetView.parentSequence<0 && widgetView.autoDockIdleDuration>0) { + [widgetView setAutoDockWithEnabled:true]; + if(ControllerUtil.activeGCControllers.count > 0) [widgetView restartAutoDockCountdown]; + } + if(sequenceGenerated){ // NSLog(@"widgetView.sequence %d %f", widgetView.sequence, CACurrentMediaTime()); buttonState.sequence = widgetView.sequence; diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 33ff9df0..eb4ccf0b 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -7406,19 +7406,19 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "\n1. 默认状态下,控件菜单按键在闲置10秒后将自动吸附屏幕底部边缘,并进入高透明状态。\n可展开控件菜单,进入“修改布局”修改该延迟。\n\n2. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n3. 展开工具箱菜单: 从%@边缘滑动%d%%屏幕宽度\n\n4. 从40%%上半边缘滑动避免触控事件影响PC端\n\n若画面出现大片发绿、发紫的颜色异常,请在主机端关闭可变显示刷新率,并将显示刷新率设定为与串流帧率一致。" + "value" : "\n1. 默认状态下,控件菜单按键在闲置3秒后将自动吸附屏幕【右下方边缘】,并进入高透明状态。\n可展开控件菜单,进入“修改布局”修改该延迟。\n\n2. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n3. 展开工具箱菜单: 从%@边缘滑动%d%%屏幕宽度\n\n4. 从40%%上半边缘滑动避免触控事件影响PC端\n\n若画面出现大片发绿、发紫的颜色异常,请在主机端关闭可变显示刷新率,并将显示刷新率设定为与串流帧率一致。" } }, "zh-Hant" : { "stringUnit" : { - "state" : "needs_review", - "value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。" + "state" : "translated", + "value" : "\n1. 預設狀態下,控件選單按鍵在閒置3秒後將自動吸附至螢幕【右下方邊緣】,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。" } }, "zh-HK" : { "stringUnit" : { - "state" : "needs_review", - "value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。" + "state" : "translated", + "value" : "\n1. 預設狀態下,控件選單按鍵在閒置3秒後將自動吸附至螢幕【右下方邊緣】,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。" } } } diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift index 8efeb1d8..f395fc93 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift @@ -388,6 +388,15 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg var hasLegacyWidget = false for case let encoded as Data in oscProfile.buttonStatesEncoded { guard let buttonState = self.profilesManager?.unarchiveButtonStateEncoded(encoded) else { continue } + + if folder != nil { + if buttonState.alias == "=widgets" + || buttonState.alias == "=pickProfile" + || buttonState.alias == "widgetTool" { + continue + } + } + if buttonState.widgetType == 1 { let widgetView = OnScreenWidgetView.widget(cmdString: buttonState.name, buttonLabel: buttonState.alias, shape: buttonState.widgetShape, profile: oscProfile) widgetView.sequence = (buttonState.sequence == -1 || folder != nil) ? { @@ -573,6 +582,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg @IBAction func clearFolderButtonTapped(_ sender: Any?) { for widget in OnScreenWidgetView.mapping.values { if widget.parentSequence == selectedWidget?.sequence, widget.sequenceSet.isEmpty { + selectedWidget?.sequenceSet.remove(widget.sequence) OnScreenWidgetView.mapping.removeValue(forKey: widget.sequence) widget.removeFromSuperview() }