Dialog detection: subprocess timeout fix and documentation#24
Draft
Dialog detection: subprocess timeout fix and documentation#24
Conversation
Add cross-platform detection and dismissal of Unity Editor modal dialogs (Windows Win32 API, macOS AppleScript, Linux xdotool/pyatspi). Dialogs block Unity's main thread, causing all RPC commands to hang with no feedback — this feature lets agents detect and dismiss them. - New `dialog list` and `dialog dismiss` commands - `status` command now surfaces detected popups with a yellow warning - DialogInfo DTO for JSON output - EditorCommands process helpers made internal for reuse Remove SuppressSafeModeDialog — it silently forced Unity into Safe Mode on compilation errors, which prevents the plugin from connecting. The dialog system is strictly better: agents can detect the "Enter Safe Mode?" dialog and click "Ignore" to stay in normal mode.
osascript on macOS can hang indefinitely if the calling process lacks Accessibility permissions. Use async ReadToEnd + WaitForExit(5s) with kill on timeout to prevent blocking the parent command.
Covers platform support (Windows/macOS/Linux), Safe Mode behavior, agent workflow patterns, and implementation details.
Extend dialog detection to also detect Unity progress bars and the startup splash window. Progress bars (EditorUtility.DisplayProgressBar, DisplayCancelableProgressBar) and the UnitySplashWindow are now treated as dialogs with optional progress/description fields. On Windows, detects msctls_progress32 child controls (reading position via PBM_GETPOS/PBM_GETRANGE) and Static text labels for descriptions. Also matches UnitySplashWindow class in addition to #32770 dialogs. DialogInfo DTO gains nullable description and progress fields, omitted from JSON when not present for backwards compatibility.
macOS: Read progress indicators and static text via AppleScript System Events API. Windows with buttons or progress indicators are now detected (previously only windows with buttons were included). Linux: Read ROLE_PROGRESS_BAR via pyatspi queryValue() and ROLE_LABEL for descriptions. The pyatspi-only path now detects any window with a progress bar regardless of role (not just ROLE_DIALOG and ROLE_ALERT). GetButtonsPyatspi replaced with GetWindowInfoPyatspi returning buttons, progress, and description as a tuple.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the dialog detection feature (a72c210, committed directly to main):
osascripthanging indefinitely on macOS when the calling process lacks Accessibility permissions. Uses asyncReadToEnd+WaitForExit(5s)with kill on timeout, preventing the CLI from blocking.DisplayProgressBar,DisplayCancelableProgressBar) are treated as dialogs with optionalprogress(0.0-1.0) anddescriptionfields.docs/dialog-detection.mdcovering platform support (Windows/macOS/Linux), Safe Mode behavior, agent workflow patterns, window classes, progress bar detection, and implementation details.Progress bar detection
Detected as dialogs with optional
descriptionandprogressfields (nullable, omitted from JSON when absent for backwards compatibility):{"title":"Building Player (busy for 35s)...","buttons":["Cancel","Skip Transcoding"],"description":"Write asset files","progress":1.0}Windows: Detects
msctls_progress32child controls viaPBM_GETPOS/PBM_GETRANGE,Statictext labels for descriptions. Matches both#32770(standard Win32 dialog) andUnitySplashWindow(editor startup loading screen).macOS: Reads
progress indicatorelements and theirvalueproperty,static textelements for descriptions. Now detects windows with progress indicators even if they have no buttons.Linux: Reads
ROLE_PROGRESS_BARvia pyatspiqueryValue(),ROLE_LABELfor descriptions. The pyatspi-only path now detects any window with a progress bar regardless of AT-SPI role.macOS finding
All macOS APIs that can read window content or interact with UI elements (AXUIElement, osascript, JXA, NSWorkspace) require Accessibility permissions. No workaround exists. The current approach (osascript + graceful timeout) is the right trade-off — full functionality from local terminals, silent degradation over SSH.
Test plan
UnitySplashWindowwith live progress updates)BuildPipeline.BuildPlayer(full build lifecycle: compiling scripts → building player → shader variants → incremental build)EditorUtility.DisplayProgressBarandDisplayCancelableProgressBarstatuscommand shows progress bars inline with dialogsdialog listreturns empty gracefully without hanging (5s timeout works)status,dialog dismissdegrade gracefullyscript eval,editor run/stop,wait)dotnet buildpasses,dotnet test163/163 pass