初始提交:terminalX 可运行态(M0/M1/M1.5 已真机验证)

- M0: libghostty SSH 终端(渲染/输入/连接)+ 白屏修复(OutputGate) + 会话状态机/自动重连
- M1: tsnet 用户态组网 + SSH-over-tsnet(fd 桥),shell 级真机验证;R5(Go+gvisor+C+++Swift 同进程) retire
- M1.5: tmux -CC 原生 tab(MVP)
- 结构: packages/(TXCore·TXTransport), apps/TerminalX, vendor/(libghostty-spm/libssh2/mbedtls/tsnet-bridge), artifacts/
- 文档: CLAUDE.md + docs/HANDOFF.md(新会话入口)
- 环境: 认证代理→依赖 vendor 本地化;Go 在 ~/.local/go;仅模拟器/未签名
- 待续: M2 mosh, tmux 多 pane, M4 安全(host key/SE)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kid
2026-07-24 10:20:46 +08:00
commit aa92d0e676
2761 changed files with 803505 additions and 0 deletions

8
vendor/MSDisplayLink/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View File

@@ -0,0 +1,378 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
506240E32C6CBFFA00605212 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506240E22C6CBFFA00605212 /* App.swift */; };
506240E52C6CBFFA00605212 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506240E42C6CBFFA00605212 /* ContentView.swift */; };
506240E72C6CBFFB00605212 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 506240E62C6CBFFB00605212 /* Assets.xcassets */; };
506240F32C6CC02C00605212 /* MSDisplayLink in Frameworks */ = {isa = PBXBuildFile; productRef = 506240F22C6CC02C00605212 /* MSDisplayLink */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
506240DF2C6CBFFA00605212 /* DLExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
506240E22C6CBFFA00605212 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
506240E42C6CBFFA00605212 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
506240E62C6CBFFB00605212 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
506240E82C6CBFFB00605212 /* Entitlement.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Entitlement.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
506240DC2C6CBFFA00605212 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
506240F32C6CC02C00605212 /* MSDisplayLink in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
506240D62C6CBFFA00605212 = {
isa = PBXGroup;
children = (
506240E12C6CBFFA00605212 /* DLExample */,
506240E02C6CBFFA00605212 /* Products */,
506240F12C6CC02C00605212 /* Frameworks */,
);
sourceTree = "<group>";
};
506240E02C6CBFFA00605212 /* Products */ = {
isa = PBXGroup;
children = (
506240DF2C6CBFFA00605212 /* DLExample.app */,
);
name = Products;
sourceTree = "<group>";
};
506240E12C6CBFFA00605212 /* DLExample */ = {
isa = PBXGroup;
children = (
506240E62C6CBFFB00605212 /* Assets.xcassets */,
506240E82C6CBFFB00605212 /* Entitlement.entitlements */,
506240E22C6CBFFA00605212 /* App.swift */,
506240E42C6CBFFA00605212 /* ContentView.swift */,
);
path = DLExample;
sourceTree = "<group>";
};
506240F12C6CC02C00605212 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
506240DE2C6CBFFA00605212 /* DLExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 506240EE2C6CBFFB00605212 /* Build configuration list for PBXNativeTarget "DLExample" */;
buildPhases = (
506240DB2C6CBFFA00605212 /* Sources */,
506240DC2C6CBFFA00605212 /* Frameworks */,
506240DD2C6CBFFA00605212 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = DLExample;
packageProductDependencies = (
506240F22C6CC02C00605212 /* MSDisplayLink */,
);
productName = DLExample;
productReference = 506240DF2C6CBFFA00605212 /* DLExample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
506240D72C6CBFFA00605212 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1540;
LastUpgradeCheck = 1540;
TargetAttributes = {
506240DE2C6CBFFA00605212 = {
CreatedOnToolsVersion = 15.4;
};
};
};
buildConfigurationList = 506240DA2C6CBFFA00605212 /* Build configuration list for PBXProject "DLExample" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 506240D62C6CBFFA00605212;
productRefGroup = 506240E02C6CBFFA00605212 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
506240DE2C6CBFFA00605212 /* DLExample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
506240DD2C6CBFFA00605212 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
506240E72C6CBFFB00605212 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
506240DB2C6CBFFA00605212 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
506240E52C6CBFFA00605212 /* ContentView.swift in Sources */,
506240E32C6CBFFA00605212 /* App.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
506240EC2C6CBFFB00605212 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
506240ED2C6CBFFB00605212 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SWIFT_COMPILATION_MODE = wholemodule;
};
name = Release;
};
506240EF2C6CBFFB00605212 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DLExample/Entitlement.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 964G86XT2P;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = NO;
GENERATE_INFOPLIST_FILE = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wiki.qaq.DLExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3,7";
};
name = Debug;
};
506240F02C6CBFFB00605212 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DLExample/Entitlement.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 964G86XT2P;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = NO;
GENERATE_INFOPLIST_FILE = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = wiki.qaq.DLExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx xros xrsimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3,7";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
506240DA2C6CBFFA00605212 /* Build configuration list for PBXProject "DLExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
506240EC2C6CBFFB00605212 /* Debug */,
506240ED2C6CBFFB00605212 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
506240EE2C6CBFFB00605212 /* Build configuration list for PBXNativeTarget "DLExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
506240EF2C6CBFFB00605212 /* Debug */,
506240F02C6CBFFB00605212 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */
506240F22C6CC02C00605212 /* MSDisplayLink */ = {
isa = XCSwiftPackageProductDependency;
productName = MSDisplayLink;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 506240D72C6CBFFA00605212 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:DLExample.xcodeproj">
</FileRef>
<FileRef
location = "group:..">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,37 @@
//
// App.swift
// DLExample
//
// Created by on 2024/8/14.
//
import SwiftUI
@main
struct App: SwiftUI.App {
var body: some Scene {
WindowGroup {
ContentView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
#if os(macOS)
.background(VisualEffectView().ignoresSafeArea())
#endif
}
#if os(macOS)
.windowStyle(.hiddenTitleBar)
.windowResizability(.contentMinSize)
#endif
}
}
#if os(macOS)
struct VisualEffectView: NSViewRepresentable {
func makeNSView(context _: Context) -> NSVisualEffectView {
let effectView = NSVisualEffectView()
effectView.state = .active
return effectView
}
func updateNSView(_: NSVisualEffectView, context _: Context) {}
}
#endif

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,63 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
//
// ContentView.swift
// DLExample
//
// Created by on 2024/8/14.
//
import MSDisplayLink
import SwiftUI
struct ContentView: View {
@State var frame: Int = 0
var body: some View {
VStack {
Text("MSDisplayLink Trigger: \(frame)")
.monospacedDigit()
.contentTransition(.numericText())
}
.animation(.interactiveSpring, value: frame)
.modifier(DisplayLinkModifier(scheduleToMainThread: true) {
frame += 1
})
.padding()
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>

21
vendor/MSDisplayLink/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Lakr Aream
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

20
vendor/MSDisplayLink/Package.swift vendored Normal file
View File

@@ -0,0 +1,20 @@
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "MSDisplayLink",
platforms: [
.iOS(.v13),
.macOS(.v11),
.macCatalyst(.v13),
.tvOS(.v13),
.visionOS(.v1),
],
products: [
.library(name: "MSDisplayLink", targets: ["MSDisplayLink"]),
],
targets: [
.target(name: "MSDisplayLink"),
]
)

73
vendor/MSDisplayLink/README.md vendored Normal file
View File

@@ -0,0 +1,73 @@
# MSDisplayLink
The missing DisplayLink driver for Apple platforms. Use CADisplayLink on UIKit and CVDisplayLink on AppKit.
Battle tested in [ColorfulX](https://github.com/Lakr233/ColorfulX)
Called MS but it has nothing to do with Microsoft. :P
## Preview
![Preview](Resources/SCR-20240814-qqri.jpeg)
## Installation
### Swift Package Manager
```swift
.package(url: "https://github.com/Lakr233/MSDisplayLink.git", from: "2.0.8")
```
### CocoaPods
**Never thought about it.**
## Usage
### UIKit/AppKit
Follow the steps to get called. The `DisplayLinkDelegate` is friendly to confirm for a UIView or NSView.
- Hold reference to `DisplayLink` object.
- Confirm to `DisplayLinkDelegate` protocol to get called within `synchronization()`.
- Call `displayLink.delegatingObject` with a `DisplayLinkDelegate` object.
Tech Tips:
- Call to `synchronization()` is performed at a background thread.
- Scheduler is a serial queue unique to each `DisplayLinkDriver` holds by `DisplayLink`.
- Queue inherits the quality of service from the where you created the `DisplayLink`.
- Does not make scene to use concurrent queue.
- Does not share the queue across different `DisplayLink` objects.
- Queue names are same.
### SwiftUI
```
import MSDisplayLink
import SwiftUI
struct ContentView: View {
@State var frame: Int = 0
var body: some View {
VStack {
Text("MSDisplayLink Trigger: \(frame)")
.monospacedDigit()
.contentTransition(.numericText())
}
.animation(.interactiveSpring, value: frame)
.modifier(DisplayLinkModifier(scheduleToMainThread: true) {
frame += 1
})
.padding()
}
}
```
## License
[MIT License](LICENSE)
---
2024.08.14

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

36
vendor/MSDisplayLink/Scripts/test.build.sh vendored Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
cd "$(dirname "$0")"
cd ..
WORKSPACE="./Example/DLExample.xcworkspace"
SCEHEME="DLExample"
function test_build() {
DESTINATION=$1
echo "[*] test build for $DESTINATION"
xcodebuild \
-workspace "$WORKSPACE" \
-scheme "$SCEHEME" \
-destination "$DESTINATION" \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_ALLOWED=NO \
| xcbeautify
EXIT_CODE=${PIPESTATUS[0]}
echo "[*] finished with exit code $EXIT_CODE"
if [ $EXIT_CODE -ne 0 ]; then
echo "[!] failed to build for $DESTINATION"
exit 1
fi
}
test_build "generic/platform=macOS"
test_build "generic/platform=macOS,variant=Mac Catalyst"
test_build "generic/platform=iOS"
test_build "generic/platform=iOS Simulator"
test_build "generic/platform=tvOS"
test_build "generic/platform=tvOS Simulator"
test_build "generic/platform=xrOS"
test_build "generic/platform=xrOS Simulator"
echo "[*] all builds succeeded"

View File

@@ -0,0 +1,56 @@
//
// DisplayLink+SwiftUI.swift
// MSDisplayLink
//
// Created by on 2024/8/14.
//
import SwiftUI
@MainActor
public struct DisplayLinkModifier: ViewModifier {
let link: DisplayLink
let context: DisplayLinkModifierContext
public init(scheduleToMainThread: Bool = true, _ callback: @escaping @Sendable (DisplayLinkCallbackContext) -> Void) {
link = .init()
context = .init(scheduleToMainThread: scheduleToMainThread, callback: callback)
link.delegatingObject(context)
}
public init(scheduleToMainThread: Bool = true, _ callback: @escaping @Sendable () -> Void) {
self.init(scheduleToMainThread: scheduleToMainThread) { _ in callback() }
}
public func body(content: Content) -> some View {
content
.onAppear { link.delegatingObject(context) }
.onDisappear { link.delegatingObject(nil) }
}
}
class DisplayLinkModifierContext: ObservableObject, DisplayLinkDelegate, @unchecked Sendable {
let scheduleToMainThread: Bool
var callback: @Sendable (DisplayLinkCallbackContext) -> Void
init(scheduleToMainThread: Bool, callback: @escaping @Sendable (DisplayLinkCallbackContext) -> Void) {
self.scheduleToMainThread = scheduleToMainThread
self.callback = callback
}
func synchronization(context: DisplayLinkCallbackContext) {
if scheduleToMainThread {
if Thread.isMainThread {
callback(context)
} else {
DispatchQueue.main.async { self.callback(context) }
}
} else {
if Thread.isMainThread {
DispatchQueue.global().async { self.callback(context) }
} else {
callback(context)
}
}
}
}

View File

@@ -0,0 +1,40 @@
//
// DisplayLink.swift
// MSDisplayLink
//
// Created by on 2024/8/13.
//
@preconcurrency import Combine
import Foundation
public protocol DisplayLinkDelegate: AnyObject {
func synchronization(context: DisplayLinkCallbackContext)
}
public class DisplayLink: @unchecked Sendable {
private weak var delegatingObject: DisplayLinkDelegate?
private var driver: DisplayLinkDriver?
private var driverSubscription: Set<AnyCancellable> = .init()
public init() {
let driver = DisplayLinkDriver()
driver.synchronizationPublisher
.sink { [weak self] output in self?.delegatingObject?.synchronization(context: output) }
.store(in: &driverSubscription)
self.driver = driver
}
deinit { teardown() }
func teardown() {
driverSubscription.forEach { $0.cancel() }
driverSubscription.removeAll()
driver = nil
}
public func delegatingObject(_ object: DisplayLinkDelegate?) {
delegatingObject = object
}
}

View File

@@ -0,0 +1,23 @@
//
// DisplayLinkCallbackContext.swift
// MSDisplayLink
//
// Created by on 2025/1/6.
//
import Foundation
public struct DisplayLinkCallbackContext: Sendable {
/// The time interval between screen refresh updates.
public let duration: TimeInterval
/// The time interval that represents when the last frame displayed.
public let timestamp: TimeInterval
/// The time interval that represents when the next frame displays.
public let targetTimestamp: TimeInterval
public init(duration: TimeInterval, timestamp: TimeInterval, targetTimestamp: TimeInterval) {
self.duration = duration
self.timestamp = timestamp
self.targetTimestamp = targetTimestamp
}
}

View File

@@ -0,0 +1,64 @@
import Foundation
#if canImport(UIKit)
import UIKit
typealias DisplayLinkDriverHelper = CADisplayLinkDriverHelper
class CADisplayLinkDriverHelper: DisplayLinkDriverHelperBase {
nonisolated(unsafe) static let shared = CADisplayLinkDriverHelper()
private var displayLink: CADisplayLink?
override private init() {
super.init()
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidEnterBackground(_:)),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillEnterForeground(_:)),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
override func startDisplayLink() {
assert(Thread.isMainThread)
guard displayLink == nil else { return }
displayLink = CADisplayLink(target: self, selector: #selector(displayLinkCallback(_:)))
displayLink?.add(to: .main, forMode: .common)
}
override func stopDisplayLink() {
assert(Thread.isMainThread)
displayLink?.invalidate()
displayLink = nil
}
@objc private func displayLinkCallback(_ displayLink: CADisplayLink) {
let context = DisplayLinkCallbackContext(
duration: displayLink.duration,
timestamp: displayLink.timestamp,
targetTimestamp: displayLink.targetTimestamp
)
autoreleasepool { dispatchUpdate(context: context) }
}
@objc private func applicationDidEnterBackground(_: Notification) {
stopDisplayLink()
}
@objc private func applicationWillEnterForeground(_: Notification) {
startDisplayLink()
}
}
#endif

View File

@@ -0,0 +1,43 @@
import Foundation
#if !canImport(UIKit) && canImport(AppKit)
import AppKit
typealias DisplayLinkDriverHelper = CVDisplayLinkDriverHelper
class CVDisplayLinkDriverHelper: DisplayLinkDriverHelperBase {
nonisolated(unsafe) static let shared = CVDisplayLinkDriverHelper()
private var displayLink: CVDisplayLink?
override func startDisplayLink() {
assert(Thread.isMainThread)
guard displayLink == nil else { return }
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)
guard let displayLink else { return }
CVDisplayLinkSetOutputCallback(displayLink, { _, inNow, inOutputTime, _, _, _ in
let clockFrequency = CVGetHostClockFrequency()
let context = DisplayLinkCallbackContext(
duration: TimeInterval(inNow.pointee.videoRefreshPeriod) / TimeInterval(inNow.pointee.videoTimeScale),
timestamp: TimeInterval(inNow.pointee.hostTime) / clockFrequency,
targetTimestamp: TimeInterval(inOutputTime.pointee.hostTime) / clockFrequency
)
assert(!Thread.isMainThread)
DispatchQueue.main.async {
autoreleasepool {
CVDisplayLinkDriverHelper.shared.dispatchUpdate(context: context)
}
}
return kCVReturnSuccess
}, nil)
CVDisplayLinkStart(displayLink)
}
override func stopDisplayLink() {
assert(Thread.isMainThread)
if let displayLink { CVDisplayLinkStop(displayLink) }
displayLink = nil
}
}
#endif

View File

@@ -0,0 +1,59 @@
//
// DisplayLinkDriver+Helper.swift
//
//
// Created by on 2024/8/29.
//
import Foundation
class DisplayLinkDriverHelperBase: Identifiable {
final let id: UUID = .init()
private(set) var referenceHolder: [WeakBox] = []
struct WeakBox { weak var object: DisplayLinkDriver? }
final func delegate(_ object: DisplayLinkDriver) {
assert(Thread.isMainThread)
var shouldStartDisplayLink = false
defer { if shouldStartDisplayLink { startDisplayLink() } }
referenceHolder = referenceHolder
.filter { $0.object != nil }
.filter { $0.object?.id != object.id }
+ [.init(object: object)]
shouldStartDisplayLink = !referenceHolder.isEmpty
}
final func remove(_ object: DisplayLinkDriver) {
assert(Thread.isMainThread)
referenceHolder = referenceHolder.filter { $0.object?.id != object.id }
}
final func reclaimComputeResourceIfPossible() {
assert(Thread.isMainThread)
var shouldStop = false
defer { if shouldStop { self.stopDisplayLink() } }
referenceHolder = referenceHolder.filter { $0.object != nil }
shouldStop = referenceHolder.isEmpty
}
final func dispatchUpdate(context: DisplayLinkCallbackContext) {
defer { self.reclaimComputeResourceIfPossible() }
for box in referenceHolder {
box.object?.synchronize(context: context)
}
}
func startDisplayLink() {
fatalError("Subclasses need to implement the `startDisplayLink()` method.")
}
func stopDisplayLink() {
fatalError("Subclasses need to implement the `stopDisplayLink()` method.")
}
}

View File

@@ -0,0 +1,32 @@
//
// DisplayLinkDriver.swift
// MSDisplayLink
//
// Created by on 2024/8/13.
//
@preconcurrency import Combine
import Foundation
class DisplayLinkDriver: Identifiable {
let id: UUID = .init()
typealias SynchornizationPublisher = PassthroughSubject<
DisplayLinkCallbackContext,
Never
>
let synchronizationPublisher: SynchornizationPublisher
init() {
synchronizationPublisher = .init()
DisplayLinkDriverHelper.shared.delegate(self)
}
deinit {
DisplayLinkDriverHelper.shared.remove(self)
}
func synchronize(context: DisplayLinkCallbackContext) {
synchronizationPublisher.send(context)
}
}