| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e6591bc commit 6ddfbf2
43 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -79,7 +79,7 @@ Private simulator behavior is implemented locally in: | |||
| 79 | 79 | ||
| 80 | 80 | The current repo uses the private boot path, private display bridge, and private accessibility translation bridge directly. The browser streams frames from that bridge, injects touch and keyboard events through the same native session layer, inspects accessibility through `AccessibilityPlatformTranslation`, and renders device chrome from `cli/XCWChromeRenderer.*`. | |
| 81 | 81 | CoreSimulator service contexts resolve the active developer directory from `DEVELOPER_DIR`, then `xcode-select -p`, then `/Applications/Xcode.app/Contents/Developer`. The display bridge prefers direct CoreSimulator screen IOSurface callbacks and activates the SimulatorKit offscreen renderable view only if direct callbacks are unavailable. | |
| 82 | - Accessibility recovery may use simulator launchctl UIKit application state plus hit-tested translations to recover candidate foreground pids; the returned tree must still be rooted at tokenized `AXPTranslator` application objects, because `translationApplicationObjectForPid:` can omit the bridge delegate token after private display lifecycle changes. Full-tree snapshots merge those recovered roots with the private frontmost application translation. When multiple candidate application roots are discovered, serialize all of them in preferred order: non-extension app roots first, then largest translated roots, with `.appex`/PlugIns processes de-prioritized so SpringBoard and Safari app roots stay primary while widgets and WebContent roots remain debuggable. Widget renderer extension roots may report local frames; normalize those roots and children against matching SpringBoard widget placeholder frames before returning the snapshot. | ||
| 82 | + Accessibility recovery may use simulator launchctl UIKit application state plus hit-tested translations to recover candidate foreground pids; the returned tree must still be rooted at tokenized `AXPTranslator` application objects, because `translationApplicationObjectForPid:` can omit the bridge delegate token after private display lifecycle changes. Full-tree snapshots merge those recovered roots with the private frontmost application translation. Shallow snapshots with `maxDepth <= 2` use the tokenized frontmost application translation directly when it is available, and only run the expensive recovery sweep if frontmost lookup fails, so agent-oriented describe loops avoid launchctl and hit-test recovery overhead. Interactive-only snapshots also prune non-actionable native AX leaves during Objective-C serialization before the Rust-side compacting pass; keep this native pruning conservative so selector taps still retain actionable rows plus their ancestors. When multiple candidate application roots are discovered, serialize all of them in preferred order: non-extension app roots first, then largest translated roots, with `.appex`/PlugIns processes de-prioritized so SpringBoard and Safari app roots stay primary while widgets and WebContent roots remain debuggable. Widget renderer extension roots may report local frames; normalize those roots and children against matching SpringBoard widget placeholder frames before returning the snapshot. | ||
| 83 | 83 | Physical chrome button support uses DeviceKit `chrome.json` input geometry for browser hit targets. Volume, action, mute, Apple Watch digital crown, Watch side button, and Watch left-side button dispatch through `IndigoHIDMessageForHIDArbitrary` with consumer/telephony/vendor HID usage pairs from the device chrome metadata; home, lock, and app-switcher remain on the existing SimulatorKit button paths. Apple Watch Digital Crown rotation dispatches through `IndigoHIDMessageForDigitalCrownEvent` when SimulatorKit exposes it, with `IndigoHIDMessageForScrollEvent(..., target=0x34)` as the fallback. tvOS simulators do not support direct screen touch; browser/API tap maps to Enter, swipe maps to arrow keys, and the native bridge rejects tvOS touch packets before they reach guest `SimulatorHID`. watchOS/tvOS skip dynamic pointer/mouse service warm-up because those guest runtimes abort on unsupported virtual services. Apple TV and Apple Watch simulators are fixed-orientation devices, so client and server rotation paths must not expose or dispatch device rotation for those families. | |
| 84 | 84 | Two-point multi-touch dispatch prefers the current SimulatorKit/Indigo packet constructor and falls back to SimDeck's manual Indigo packet adapter. On Xcode 26 SimulatorKit, the constructor expects pixel-space points and stable two-finger movement requires sending `LeftMouseDown` for both `began` and `moved`, then `LeftMouseUp` for `ended`/`cancelled`; using `LeftMouseDragged` for multi-touch moves only advances one contact in UIKit. Do not coalesce multi-touch move packets in the WebSocket or WebRTC control paths, because gesture recognizers need the intermediate two-contact samples. | |
| 85 | 85 | WebKit inspection uses the simulator `webinspectord` Unix socket named `com.apple.webinspectord_sim.socket` and WebKit's binary-plist Remote Inspector selectors. It lists only WebKit content that the runtime exposes as inspectable. For app-owned `WKWebView` on iOS 16.4 and newer, the app must set `isInspectable = true`. | |
@@ -137,32 +137,43 @@ Useful direct commands: | |||
| 137 | 137 | ||
| 138 | 138 | ```sh | |
| 139 | 139 | ./build/simdeck list | |
| 140 | + ./build/simdeck use <udid> | ||
| 140 | 141 | ./build/simdeck boot <udid> | |
| 141 | - ./build/simdeck shutdown <udid> | ||
| 142 | - ./build/simdeck erase <udid> | ||
| 143 | - ./build/simdeck install <udid> /path/to/App.app | ||
| 144 | - ./build/simdeck uninstall <udid> com.example.App | ||
| 145 | - ./build/simdeck open-url <udid> https://example.com | ||
| 146 | - ./build/simdeck launch <udid> com.apple.Preferences | ||
| 147 | - ./build/simdeck pasteboard set <udid> "hello" | ||
| 148 | - ./build/simdeck pasteboard get <udid> | ||
| 149 | - ./build/simdeck screenshot <udid> --output screen.png | ||
| 150 | - ./build/simdeck screenshot <udid> --with-bezel --output screen-bezel.png | ||
| 151 | - ./build/simdeck record <udid> --seconds 5 --output screen-recording.mp4 | ||
| 152 | - ./build/simdeck describe <udid> | ||
| 153 | - ./build/simdeck tap <udid> 120 240 | ||
| 154 | - ./build/simdeck tap <udid> --label "Continue" --wait-timeout-ms 5000 | ||
| 155 | - ./build/simdeck swipe <udid> 200 700 200 200 | ||
| 156 | - ./build/simdeck gesture <udid> scroll-down | ||
| 157 | - ./build/simdeck pinch <udid> --start-distance 160 --end-distance 80 | ||
| 158 | - ./build/simdeck rotate-gesture <udid> --radius 100 --degrees 90 | ||
| 159 | - ./build/simdeck key-sequence <udid> --keycodes h,e,l,l,o | ||
| 160 | - ./build/simdeck key-combo <udid> --modifiers cmd --key a | ||
| 161 | - ./build/simdeck type <udid> "hello" | ||
| 162 | - ./build/simdeck button <udid> lock --duration-ms 1000 | ||
| 163 | - ./build/simdeck home <udid> | ||
| 142 | + ./build/simdeck shutdown | ||
| 143 | + ./build/simdeck erase | ||
| 144 | + ./build/simdeck install /path/to/App.app | ||
| 145 | + ./build/simdeck uninstall com.example.App | ||
| 146 | + ./build/simdeck open-url https://example.com | ||
| 147 | + ./build/simdeck launch com.apple.Preferences | ||
| 148 | + ./build/simdeck pasteboard set "hello" | ||
| 149 | + ./build/simdeck pasteboard get | ||
| 150 | + ./build/simdeck screenshot --output screen.png | ||
| 151 | + ./build/simdeck screenshot --with-bezel --output screen-bezel.png | ||
| 152 | + ./build/simdeck record --seconds 5 --output screen-recording.mp4 | ||
| 153 | + ./build/simdeck describe --format agent --max-depth 4 -i | ||
| 154 | + ./build/simdeck wait-for --label "Welcome" --timeout-ms 5000 | ||
| 155 | + ./build/simdeck tap 120 240 | ||
| 156 | + ./build/simdeck tap --label "Continue" --wait-timeout-ms 5000 | ||
| 157 | + ./build/simdeck tap "Continue" | ||
| 158 | + ./build/simdeck tap --id com.apple.settings.screenTime --expect-id BackButton | ||
| 159 | + ./build/simdeck back | ||
| 160 | + ./build/simdeck swipe 200 700 200 200 | ||
| 161 | + ./build/simdeck gesture scroll-down | ||
| 162 | + ./build/simdeck pinch --start-distance 160 --end-distance 80 | ||
| 163 | + ./build/simdeck rotate-gesture --radius 100 --degrees 90 | ||
| 164 | + ./build/simdeck key-sequence --keycodes h,e,l,l,o | ||
| 165 | + ./build/simdeck key-combo --modifiers cmd --key a | ||
| 166 | + ./build/simdeck type "hello" | ||
| 167 | + ./build/simdeck button lock --duration-ms 1000 | ||
| 168 | + ./build/simdeck home | ||
| 164 | 169 | ``` | |
| 165 | 170 | ||
| 171 | + Most simulator commands accept `[<udid>]`; when it is omitted, SimDeck uses | ||
| 172 | + `--device`, `SIMDECK_DEVICE`, `SIMDECK_UDID`, the saved project default, or the | ||
| 173 | + only booted simulator, in that order. For agent navigation, prefer | ||
| 174 | + `describe -i`, `wait-for`, `tap --id/--label`, `tap "Text"`, `back`, and | ||
| 175 | + `batch` over coordinate-only loops. | ||
| 176 | + | ||
| 166 | 177 | ## Expectations For Future Changes | |
| 167 | 178 | ||
| 168 | 179 | - If you add an API route, add the matching client affordance or document why it stays CLI-only. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -94,131 +94,89 @@ CLI commands automatically use the same warm daemon: | |||
| 94 | 94 | ||
| 95 | 95 | ```sh | |
| 96 | 96 | simdeck list | |
| 97 | - simdeck tap <udid> 0.5 0.5 --normalized | ||
| 98 | - simdeck describe <udid> --format agent --max-depth 2 | ||
| 99 | - ``` | ||
| 100 | - | ||
| 101 | - ## Daemon | ||
| 102 | - | ||
| 103 | - Manage the project daemon explicitly when needed: | ||
| 104 | - | ||
| 105 | - ```sh | ||
| 106 | - simdeck daemon start | ||
| 107 | - simdeck daemon restart | ||
| 108 | - simdeck daemon status | ||
| 109 | - simdeck daemon stop | ||
| 110 | - simdeck daemon killall | ||
| 111 | - ``` | ||
| 112 | - | ||
| 113 | - `simdeck daemon` manages the normal per-project warm process. `daemon killall` | ||
| 114 | - stops SimDeck daemons across all workspaces. | ||
| 115 | - | ||
| 116 | - Use software H.264 when the hardware encoder is unavailable, busy, or starved | ||
| 117 | - by screen recording: | ||
| 118 | - | ||
| 119 | - ```sh | ||
| 120 | - simdeck daemon start --video-codec software | ||
| 121 | - ``` | ||
| 122 | - | ||
| 123 | - Restart the CoreSimulator service layer when `simctl` reports a stale service | ||
| 124 | - version or the live display gets stuck before the first frame: | ||
| 125 | - | ||
| 126 | - ```sh | ||
| 127 | - simdeck core-simulator restart | ||
| 128 | - ``` | ||
| 129 | - | ||
| 130 | - You can also start or stop the CoreSimulator service layer explicitly: | ||
| 131 | - | ||
| 132 | - ```sh | ||
| 133 | - simdeck core-simulator start | ||
| 134 | - simdeck core-simulator shutdown | ||
| 97 | + simdeck use <udid> | ||
| 98 | + simdeck tap 0.5 0.5 --normalized | ||
| 99 | + simdeck tap "Continue" | ||
| 100 | + simdeck describe --format agent --max-depth 2 --interactive | ||
| 101 | + simdeck press @e3 | ||
| 102 | + simdeck snapshot --format agent --max-depth 2 -i | ||
| 103 | + simdeck --device <other-udid> describe --format agent --max-depth 2 | ||
| 135 | 104 | ``` | |
| 136 | 105 | ||
| 137 | 106 | ## CLI | |
| 138 | 107 | ||
| 139 | 108 | ```sh | |
| 140 | 109 | simdeck list | |
| 110 | + simdeck use <udid> | ||
| 141 | 111 | simdeck boot <udid> | |
| 142 | - simdeck shutdown <udid> | ||
| 143 | - simdeck erase <udid> | ||
| 144 | - simdeck install <udid> /path/to/App.app | ||
| 145 | - simdeck install <udid> /path/to/App.ipa | ||
| 112 | + simdeck shutdown | ||
| 113 | + simdeck erase | ||
| 114 | + simdeck install /path/to/App.app | ||
| 115 | + simdeck install /path/to/App.ipa | ||
| 146 | 116 | simdeck install android:<avd-name> /path/to/app.apk | |
| 147 | - simdeck uninstall <udid> com.example.App | ||
| 148 | - simdeck open-url <udid> https://example.com | ||
| 149 | - simdeck launch <udid> com.apple.Preferences | ||
| 150 | - simdeck toggle-appearance <udid> | ||
| 151 | - simdeck pasteboard set <udid> "hello" | ||
| 152 | - simdeck pasteboard get <udid> | ||
| 153 | - simdeck screenshot <udid> --output screen.png | ||
| 154 | - simdeck screenshot <udid> --with-bezel --output screen-bezel.png | ||
| 155 | - simdeck record <udid> --seconds 5 --output screen-recording.mp4 | ||
| 156 | - simdeck stream <udid> --frames 120 > stream.h264 | ||
| 157 | - simdeck describe <udid> | ||
| 158 | - simdeck describe <udid> --format agent --max-depth 4 | ||
| 159 | - simdeck describe <udid> --point 120,240 | ||
| 160 | - simdeck wait-for <udid> --label "Welcome" --timeout-ms 5000 | ||
| 161 | - simdeck assert <udid> --id login.button --source auto --max-depth 8 | ||
| 162 | - simdeck tap <udid> 120 240 | ||
| 163 | - simdeck tap <udid> --label "Continue" --wait-timeout-ms 5000 | ||
| 164 | - simdeck swipe <udid> 200 700 200 200 | ||
| 165 | - simdeck gesture <udid> scroll-down | ||
| 166 | - simdeck pinch <udid> --start-distance 160 --end-distance 80 | ||
| 167 | - simdeck rotate-gesture <udid> --radius 100 --degrees 90 | ||
| 168 | - simdeck touch <udid> 0.5 0.5 --phase began --normalized | ||
| 169 | - simdeck touch <udid> 120 240 --down --up --delay-ms 800 | ||
| 170 | - simdeck key <udid> enter | ||
| 171 | - simdeck key-sequence <udid> --keycodes h,e,l,l,o | ||
| 172 | - simdeck key-combo <udid> --modifiers cmd --key a | ||
| 173 | - simdeck type <udid> "hello" | ||
| 174 | - simdeck type <udid> --file message.txt | ||
| 175 | - simdeck button <udid> lock --duration-ms 1000 | ||
| 176 | - simdeck button <udid> volume-up | ||
| 177 | - simdeck button <udid> action --duration-ms 1000 | ||
| 178 | - simdeck button <udid> digital-crown | ||
| 179 | - simdeck crown <udid> --delta 50 | ||
| 180 | - simdeck button <udid> left-side-button | ||
| 181 | - simdeck batch <udid> --step "tap --label Continue" --step "type 'hello'" --step "wait-for --label hello" | ||
| 182 | - simdeck dismiss-keyboard <udid> | ||
| 183 | - simdeck button <udid> software-keyboard | ||
| 184 | - simdeck home <udid> | ||
| 185 | - simdeck app-switcher <udid> | ||
| 186 | - simdeck rotate-left <udid> | ||
| 187 | - simdeck rotate-right <udid> | ||
| 188 | - simdeck chrome-profile <udid> | ||
| 189 | - simdeck logs <udid> --seconds 30 --limit 200 | ||
| 190 | - simdeck processes <udid> | ||
| 191 | - simdeck stats <udid> --watch | ||
| 192 | - simdeck sample <udid> --seconds 3 | ||
| 117 | + simdeck uninstall com.example.App | ||
| 118 | + simdeck open-url https://example.com | ||
| 119 | + simdeck launch com.apple.Preferences | ||
| 120 | + simdeck toggle-appearance | ||
| 121 | + simdeck pasteboard set "hello" | ||
| 122 | + simdeck pasteboard get | ||
| 123 | + simdeck screenshot --output screen.png | ||
| 124 | + simdeck screenshot --with-bezel --output screen-bezel.png | ||
| 125 | + simdeck record --seconds 5 --output screen-recording.mp4 | ||
| 126 | + simdeck stream --frames 120 > stream.h264 | ||
| 127 | + simdeck describe | ||
| 128 | + simdeck describe --format agent --max-depth 4 | ||
| 129 | + simdeck describe --format agent --max-depth 4 --interactive | ||
| 130 | + simdeck snapshot --format agent --max-depth 4 -i | ||
| 131 | + simdeck describe --point 120,240 | ||
| 132 | + simdeck wait-for --label "Welcome" --timeout-ms 5000 | ||
| 133 | + simdeck wait --label "Welcome" --timeout-ms 5000 | ||
| 134 | + simdeck assert --id login.button --source auto --max-depth 8 | ||
| 135 | + simdeck tap 120 240 | ||
| 136 | + simdeck tap --label "Continue" --wait-timeout-ms 5000 | ||
| 137 | + simdeck tap --id com.apple.settings.screenTime --expect-id BackButton | ||
| 138 | + simdeck tap "Continue" | ||
| 139 | + simdeck press @e3 | ||
| 140 | + simdeck back | ||
| 141 | + simdeck swipe 200 700 200 200 | ||
| 142 | + simdeck gesture scroll-down | ||
| 143 | + simdeck pinch --start-distance 160 --end-distance 80 | ||
| 144 | + simdeck rotate-gesture --radius 100 --degrees 90 | ||
| 145 | + simdeck touch 0.5 0.5 --phase began --normalized | ||
| 146 | + simdeck touch 120 240 --down --up --delay-ms 800 | ||
| 147 | + simdeck key enter | ||
| 148 | + simdeck key-sequence --keycodes h,e,l,l,o | ||
| 149 | + simdeck key-combo --modifiers cmd --key a | ||
| 150 | + simdeck type "hello" | ||
| 151 | + simdeck type --file message.txt | ||
| 152 | + simdeck button lock --duration-ms 1000 | ||
| 153 | + simdeck button volume-up | ||
| 154 | + simdeck button action --duration-ms 1000 | ||
| 155 | + simdeck button digital-crown | ||
| 156 | + simdeck crown --delta 50 | ||
| 157 | + simdeck button left-side-button | ||
| 158 | + simdeck batch --step "tap --label Continue --expect-label Done" --step "type 'hello'" --step "back" | ||
| 159 | + simdeck dismiss-keyboard | ||
| 160 | + simdeck button software-keyboard | ||
| 161 | + simdeck home | ||
| 162 | + simdeck app-switcher | ||
| 163 | + simdeck rotate-left | ||
| 164 | + simdeck rotate-right | ||
| 165 | + simdeck chrome-profile | ||
| 166 | + simdeck logs --seconds 30 --limit 200 | ||
| 167 | + simdeck processes | ||
| 168 | + simdeck stats --watch | ||
| 169 | + simdeck sample --seconds 3 | ||
| 193 | 170 | ``` | |
| 194 | 171 | ||
| 195 | 172 | `simdeck list` defaults to compact JSON for agent-friendly device selection. | |
| 196 | 173 | Use `simdeck list --format json` for the full inventory with paths and display | |
| 197 | 174 | metadata. | |
| 198 | 175 | ||
| 199 | - `boot` uses SimDeck's private CoreSimulator boot path so it can start devices | ||
| 200 | - without launching Simulator.app. If that private path is unavailable, the | ||
| 201 | - command returns the CoreSimulator error instead of falling back to | ||
| 202 | - `xcrun simctl boot`. | ||
| 203 | - | ||
| 204 | - Android emulators appear in `simdeck list` with IDs like | ||
| 205 | - `android:SimDeck_Pixel_8_API_36`. For Android IDs, lifecycle, install, launch, | ||
| 206 | - URL, screenshot, logs, UIAutomator `describe`, tap, swipe, text, key, home, app | ||
| 207 | - switcher, rotation, pasteboard, and browser live view route through the Android | ||
| 208 | - SDK tools (`emulator` and `adb`) plus the emulator gRPC screenshot stream for | ||
| 209 | - live video. `simdeck stream` remains iOS-only because it writes the iOS H.264 | ||
| 210 | - transport stream. | ||
| 211 | - | ||
| 212 | - `stream` writes an Annex B H.264 elementary stream to stdout for diagnostics or | ||
| 213 | - external tools such as `ffplay`. | ||
| 214 | - | ||
| 215 | - `describe` uses the project daemon to prefer React Native, NativeScript, | ||
| 216 | - Flutter, or UIKit in-app inspectors, then falls back to the built-in private | ||
| 217 | - CoreSimulator accessibility bridge. Use `--format agent` or | ||
| 218 | - `--format compact-json` for | ||
| 219 | - lower-token hierarchy dumps. Coordinate commands accept screen coordinates from | ||
| 220 | - the accessibility tree by default; pass `--normalized` to send `0.0..1.0` | ||
| 221 | - coordinates directly. | ||
| 176 | + `simdeck use <udid>` stores a default simulator for the current project | ||
| 177 | + directory. Most device commands accept `[<udid>]`; when it is omitted, SimDeck | ||
| 178 | + uses `--device`, `SIMDECK_DEVICE`, `SIMDECK_UDID`, the saved project default, | ||
| 179 | + or the only booted simulator, in that order. | ||
| 222 | 180 | ||
| 223 | 181 | ## JS/TS Tests | |
| 224 | 182 | ||
@@ -240,7 +198,11 @@ try { | |||
| 240 | 198 | `connect()` starts the project daemon when needed, reuses it when it is already | |
| 241 | 199 | healthy, and only stops daemons it started itself. Pass `udid` to `connect()` | |
| 242 | 200 | to make it the default for session methods; each method still accepts an | |
| 243 | - explicit UDID as the first argument when needed. | ||
| 201 | + explicit UDID as the first argument when needed. Query helpers such as | ||
| 202 | + `tree()`, `query()`, `waitFor()`, `assert()`, and selector `tapElement()` | ||
| 203 | + default to `source: "native-ax"` for fast agent control; pass | ||
| 204 | + `source: "auto"` when a test intentionally wants richer framework inspector | ||
| 205 | + trees first. | ||
| 244 | 206 | ||
| 245 | 207 | ## NativeScript Inspector | |
| 246 | 208 | ||
@@ -297,13 +259,6 @@ void main() { | |||
| 297 | 259 | } | |
| 298 | 260 | ``` | |
| 299 | 261 | ||
| 300 | - ## VS Code | ||
| 301 | - | ||
| 302 | - Install the `nativescript.simdeck-vscode` extension from the VS Code Marketplace, then | ||
| 303 | - run `SimDeck: Open Simulator View` from the Command Palette. The extension | ||
| 304 | - opens the simulator inside a VS Code panel and auto-starts the local daemon | ||
| 305 | - when it is not already reachable. | ||
| 306 | - | ||
| 307 | 262 | ## Contributing | |
| 308 | 263 | ||
| 309 | 264 | Contributors should read [CONTRIBUTING.md](CONTRIBUTING.md) for local build | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN | |||
| 7 | 7 | + (nullable NSDictionary *)accessibilitySnapshotForSimulatorUDID:(NSString *)udid | |
| 8 | 8 | atPoint:(nullable NSValue *)pointValue | |
| 9 | 9 | maxDepth:(NSUInteger)maxDepth | |
| 10 | + interactiveOnly:(BOOL)interactiveOnly | ||
| 10 | 11 | error:(NSError * _Nullable * _Nullable)error; | |
| 11 | 12 | ||
| 12 | 13 | @end | |
| Back | FazBrowse Home | New Git URL |
0 commit comments