Skip to content

fix: use canceled instead of performed for MainMenu shortcut to prevent Cmd+Tab regression - #9744

Open
decentraland-bot wants to merge 2 commits into
devfrom
fix/7348-cmd-tab-opens-explore-menu
Open

fix: use canceled instead of performed for MainMenu shortcut to prevent Cmd+Tab regression#9744
decentraland-bot wants to merge 2 commits into
devfrom
fix/7348-cmd-tab-opens-explore-menu

Conversation

@decentraland-bot

Copy link
Copy Markdown
Contributor

Pull Request Description

What does this PR change?

Fixes a regression where pressing Cmd+Tab on macOS to switch between the Explorer and another app opens the Explore Menu when returning to the Explorer.

Root cause: PR #6576 ("replace shared space manager", merged April 2026) introduced ExplorePanelPlugin.cs which subscribes to dclInput.Shortcuts.MainMenu.performed. The original fix in PR #7433 had correctly changed this from .performed to .canceled in the previous files, but the new plugin re-introduced the old .performed behavior.

When .performed is used, macOS Cmd+Tab causes the Tab "performed" event to fire in Unity — the OS captures the Cmd key but the Tab key press still reaches Unity, triggering the Explore Menu to open. With .canceled, the menu only opens on key release, and since the release happens in the other app, Unity never sees it.

Changes:

  • ExplorePanelPlugin.cs: Changed MainMenu.performedMainMenu.canceled for both subscribe and unsubscribe
  • Renamed the handler method from OnInputShortcutsMainMenuPerformedAsyncOnInputShortcutsMainMenuCanceledAsync for consistency with ExplorePanelController.cs (which already uses .canceled)

Closes #7348

Test Instructions

Steps (standard run):

metaforge explorer run XXXX  # ← replace with this PR number

Expected result:

  1. Open the Explorer on macOS
  2. Press Cmd+Tab to switch to another app (e.g. Slack, VSCode)
  3. Press Cmd+Tab to return to the Explorer
  4. The Explore Menu should NOT open — the game should resume exactly as you left it

Steps (fresh account):

metaforge account create --clear
metaforge explorer run XXXX  # ← replace with this PR number

Expected result:
Same as above — Cmd+Tab should not open the Explore Menu.

Prerequisites

  • macOS machine required to reproduce (this is a Mac-only issue)

Test Steps

  1. Launch the Explorer and enter a scene
  2. Press Cmd+Tab to switch to another application
  3. Press Cmd+Tab to return to the Explorer
  4. Verify the Explore Menu does NOT open
  5. Repeat steps 2-4 several times (the bug was reported at ~90% repro rate)
  6. Verify that pressing Tab directly still opens the Explore Menu as expected

Additional Testing Notes

Quality Checklist


🤖 Created via Slack with Claude

Requested by Pravus (<@UDJQDQC0Z>)

…nt Cmd+Tab opening Explore Menu

PR #6576 introduced ExplorePanelPlugin.cs which subscribed to MainMenu.performed,
re-introducing the macOS Cmd+Tab bug that PR #7433 had fixed. When .performed is used,
macOS Cmd+Tab causes the Tab key press event to fire in Unity (the OS captures Cmd but
not Tab), which opens the Explore Menu. With .canceled, the menu only opens on key
release, so switching apps no longer triggers it.

Closes #7348
@decentraland-bot
decentraland-bot requested review from a team as code owners August 13, 2026 23:06
@decentraland-bot decentraland-bot added the ext-contribution Identifies a contribution which was not initiated by a Unity Developer label Aug 13, 2026
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

🚦 CI Status

Build

Build skipped — no changes detected under Explorer/.

Lint

Warnings not reduced: 13156 => 13156 — remove at least 1 warning to merge.

Warnings/errors in files changed by this PR (17)
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:786  CSharpWarnings::CS8618  Non-nullable property 'EventInfoPrefab' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:784  CSharpWarnings::CS8618  Non-nullable property 'PlaceCategoriesSO' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:785  CSharpWarnings::CS8618  Non-nullable property 'PlaceDetailPanelPrefab' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:787  CSharpWarnings::CS8618  Non-nullable property 'QualityPresets' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:772  CSharpWarnings::CS8618  Non-nullable property 'pointAtMarkerVisibilitySettings' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:786  InconsistentNaming  Name 'EventInfoPrefab' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'eventInfoPrefab'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:785  InconsistentNaming  Name 'PlaceDetailPanelPrefab' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'placeDetailPanelPrefab'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:787  InconsistentNaming  Name 'QualityPresets' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'qualityPresets'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:137  InconsistentNaming  Name 'assetBundleURL' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'assetBundleUrl'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:161  InconsistentNaming  Name 'marketplaceCreditsAPIClient' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'marketplaceCreditsApiClient'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:265  InconsistentNaming  Name 'marketplaceCreditsAPIClient' does not match rule 'parameters_should_be_camel_case'. Suggested name is 'marketplaceCreditsApiClient'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:107  InconsistentNaming  Name 'placesAPIService' does not match rule 'non_public_members_should_be_camel_case'. Suggested name is 'placesApiService'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:200  InconsistentNaming  Name 'placesAPIService' does not match rule 'parameters_should_be_camel_case'. Suggested name is 'placesApiService'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:772  InconsistentNaming  Name 'pointAtMarkerVisibilitySettings' does not match rule 'members_should_be_pascal_case'. Suggested name is 'PointAtMarkerVisibilitySettings'.
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:10  RedundantUsingDirective  Using directive is not required by the code and can be safely removed
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:88  RedundantUsingDirective  Using directive is not required by the code and can be safely removed
Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs:476  UnusedVariable  Local variable 'placeToastController' is never used

Tests

All Unity tests passed ✅

TESTS SUITE Result Passed Failed Skipped
EditMode ✅ Passed 24971 0 13
PlayMode ✅ Passed 236 0 36

@github-actions

Copy link
Copy Markdown
Contributor

Slack notification sent to #explorer-ext-contributions for external review.
To re-send, delete this comment and re-add the ext-contribution label.

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: fix: use canceled instead of performed for MainMenu shortcut to prevent Cmd+Tab regression

STEP 2 — Root-cause check ✅

Problem: PR #6576 ("replace shared space manager", April 2026) introduced ExplorePanelPlugin.cs which subscribes to dclInput.Shortcuts.MainMenu.performed. This re-introduced the Cmd+Tab regression that PR #7433 had originally fixed by switching from .performed to .canceled.

Root cause: On macOS, Cmd+Tab causes the OS to capture the Cmd key, but the Tab key press still fires in Unity as a .performed event — triggering the Explore Menu to open. With .canceled (key release), the release happens in the other app, so Unity never sees it.

Verdict: The diff fixes the actual cause — the wrong Input System event phase — not a symptom. PASS.

STEP 3 — Design & integration ✅

No new units introduced. This is a 3-line correction to an existing subscription in an existing plugin. No new classes, no new state, no new lifecycle owners.

Pattern consistency verified. ExplorePanelController.cs already uses .canceled for MainMenu:

  • dclInput.Shortcuts.MainMenu.canceled += OnCloseMainMenu;
  • dclInput.Shortcuts.MainMenu.canceled -= OnCloseMainMenu;

The two subscribers are complementary — the plugin opens the menu when State is ViewHidden, while the controller closes the menu when it is visible. No conflict.

Teardown trace:

  • Subscribe: dclInput.Shortcuts.MainMenu.canceled += OnInputShortcutsMainMenuCanceledAsync; (InitializeAsync, line 370)
  • Unsubscribe: dclInput.Shortcuts.MainMenu.canceled -= OnInputShortcutsMainMenuCanceledAsync; (Dispose, line 357)
  • ✅ Properly paired.

STEP 4 — Member audit ✅

OnInputShortcutsMainMenuCanceledAsync — private method, used solely as an event handler (1 consumer: the input event subscription). Appropriate for its role. The rename from ...Performed... to ...Canceled... correctly reflects the new event phase.

STEP 5 — Line-level review ✅

No blocking issues found. All three changes are symmetric and correct:

  1. Subscribe line updated to .canceled with renamed handler
  2. Unsubscribe line updated to .canceled with renamed handler
  3. Method renamed to match the event phase

No resource leaks, no security issues, no performance concerns, no missing error handling.

Security review ✅

No security issues found. The change only affects which Input System event phase triggers the menu — no secrets, injection surfaces, auth changes, or sensitive data exposure.

STEP 8 — Non-blocking warnings

None.


REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: Single-file fix changing input event subscription from .performed to .canceled — no ECS, async, or architecture changes.
QA_REQUIRED: YES


Reviewed by Jarvis 🤖 · Requested by Pravus (<@UDJQDQC0Z>) via Slack

@decentraland-bot

This comment has been minimized.

@pravusjif pravusjif self-assigned this Aug 14, 2026
@pravusjif pravusjif moved this to QA in Creators Tools Aug 14, 2026
@decentraland-bot

Copy link
Copy Markdown
Contributor Author

PR #9744, run #31812163080

Builds: Windows change, Windows baseline, macOS change, macOS baseline

How to read this table
  • Each build is measured 3 times. The values are the median, and (min–max) is the lowest and highest of those runs — a wide range means the metric is noisy and small differences are not trustworthy.
  • Δ is Change minus Baseline (a negative Δ means Change is faster).
  • 🟢 faster / 🔴 slower — a real difference: larger than both 3% and the run-to-run range.
  • ⚪ within noise — the difference is smaller than how much the build varies between its own runs, so it cannot be told apart from random variation. Treat it as no change.
  • Exceptions per run — the average number of exceptions in a run's log; more than the baseline is flagged 🔴 even when frame times look fine. The Exception breakdown under each table groups them by the explorer's report category and exception type (as totals across the runs).
  • A run that logged unusually many exceptions (at least 10 and 5× the median of its build's runs — e.g. a service was down during it) is excluded from all numbers and called out under the table.

Intel Core i5

Metric Baseline Change Δ Result
Samples 2287 (×3) 2404 (×3)
CPU average 39.2 ms (36.8–39.3) 37.1 ms (35.9–37.6) -2.1 ms ⚪ within noise
CPU 1% worst 378.9 ms (366.5–380.5) 289.4 ms (278.5–291.0) -89.4 ms 🟢 24% faster
CPU 0.1% worst 395.9 ms (389.0–396.8) 303.9 ms (295.6–304.1) -92.0 ms 🟢 23% faster
GPU average 9.5 ms (9.4–9.6) 9.3 ms (8.4–9.3) -0.2 ms ⚪ within noise
GPU 1% worst 40.2 ms (39.7–40.3) 29.9 ms (23.6–30.5) -10.3 ms 🟢 26% faster
GPU 0.1% worst 48.7 ms (44.9–49.0) 35.8 ms (35.6–36.2) -12.8 ms 🟢 26% faster
Exceptions per run 66 66 0 ⚪ none new
Exception breakdown
Exception Baseline (3 runs) Change (3 runs)
[UI] DllNotFoundException 192 192
[ENGINE] NullReferenceException 3 3
[ENGINE] ObjectDisposedException 3 3

Apple M1

Metric Baseline Change Δ Result
Samples 4021 (×3) 4072 (×3)
CPU average 22.3 ms (21.7–23.2) 21.9 ms (21.2–22.0) -0.3 ms ⚪ within noise
CPU 1% worst 230.5 ms (224.7–232.1) 226.2 ms (164.4–229.2) -4.4 ms ⚪ within noise
CPU 0.1% worst 238.5 ms (234.0–239.6) 231.4 ms (227.6–237.3) -7.1 ms ⚪ within noise
GPU average 6.9 ms (2.7–7.2) 2.5 ms (2.4–6.0) -4.4 ms 🟢 64% faster
GPU 1% worst 35.3 ms (33.7–37.2) 34.2 ms (34.1–34.3) -1.2 ms ⚪ within noise
GPU 0.1% worst 36.3 ms (35.1–38.0) 35.6 ms (35.1–35.9) -0.7 ms ⚪ within noise
Exceptions per run 0 0 0 ⚪ none new

@pravusjif pravusjif added bug Something isn't working no-warning-ratchet Prevent CI linting checks and removed ext-contribution Identifies a contribution which was not initiated by a Unity Developer labels Aug 14, 2026
@pravusjif
pravusjif enabled auto-merge (squash) August 14, 2026 18:58
@balducciv

Copy link
Copy Markdown

✅ PR reviewed and approved by QA on both platforms following the PR test instructions.
✅ Smoke test performed on Windows and Mac to verify the normal flow is working as expected.

Build: v0.168.0-alpha-fix/7348-cmd-tab-opens-explore-menu-6d861da
OS: macOS (M3 Pro) / Windows 11 (Intel i7-12650H, MSI Katana 15)

Test results:

  • Build version confirmed matching PR branch + commit on both platforms
  • Cmd+Tab repro loop (switch to another app and back, repeated several cycles) on Mac — Explore Menu did NOT open, stayed closed every time
  • Direct Tab press still opens/closes the Explore Menu normally (sanity check)
  • Windows smoke test — normal flow unaffected (expected, as Alt+Tab doesn't share this code path)
  • Player.log session health confirmed on both platforms — clean Current loading stage: Completed, no ExplorePanelPlugin/input-related exceptions

Unrelated errors noted (do not affect verdict):

  • Windows: WebSocketExceptionRPC Transport failed in RPCCommunitiesService (~19:09:53) — Communities/social service connectivity issue, unrelated to this input-system fix
  • Shutdown-phase noise on Mac exit (SidebarController, MVCManager, LiveKitMovementMessageBus, DynamicWorldContainer disposal) — standard teardown noise, not related to this fix

Verdict: PASS ✅

Root cause and fix confirmed: .performed.canceled correctly prevents the Tab key-press event from firing during Cmd+Tab app switching, matching the working pattern already used in ExplorePanelController.cs.

Player 9744.log

Player 9744 windows.log

14.08.2026_16.11.09_REC.9744.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working no-warning-ratchet Prevent CI linting checks

Projects

Status: QA

Development

Successfully merging this pull request may close these issues.

[QA] Explorer | Switching between explorer and other apps opens the Explore Menu

3 participants