Skip to content

Bug: quickfiler-dropdown-796-post-merge-review-residuals #808

Description

@drmoisan
  • Work Mode: minor-audit

Summary

PR #807 (issue #796, folder drop-down closes on open and click does not select) merged with four non-blocking review findings and one untested seam in the same three files. The most consequential is CR-3: the new AC2 self-inflicted-deactivation guard in QfcFormController.ParkFocusAndCancelSelectors also gates the #791 Cancel teardown caller, where its predicate has no meaning, so the teardown's synchronous selector-cancel stage is skipped whenever a breadcrumb popup is open and the popup is only closed later by a fire-and-forget reset. The others are a commit-pending latch that is never cleared on consumption (CR-2), a stale comment that now contradicts the guard placement (CR-1), a dead internal accessor (CR-4), and no automated test on the AC2 producer side (CR-7). Source: code-review.2026-09-07T17-05.md in the #796 feature folder and the Follow-ups section of PR #807.

Environment

Steps to Reproduce

  1. Launch QuickFiler and open the folder drop-down on any item so a ToolStripDropDown popup is open.
  2. Trigger Cancel (the Bug: quickfiler-high-confidence-cancel-teardown-and-deadline-defects #791 ordered teardown) while the popup is open.
  3. Observe that the park-focus teardown stage skips every selector cancel because the AC2 guard treats the open popup as a self-inflicted deactivation, and that the popup is closed only later by ResetBreadcrumb via a posted, fire-and-forget reset.
  4. For CR-2: open the popup, commit a selection (sets the commit-pending latch), then cause the next open to throw before ShowPopup runs; RestoreAfterOpenFailure calls FinishClose(Uncommitted) and the stale latch suppresses the cancel, leaving a selector session open with no popup.

Expected Behavior

  • The AC2 guard applies only to the Form.Deactivate caller; the Cancel teardown's park-focus stage cancels every open selector synchronously as the Bug: quickfiler-high-confidence-cancel-teardown-and-deadline-defects #791 ordering requires.
  • The commit-pending latch lives for exactly one popup lifetime on every path, including open failure.
  • Comments in BreadcrumbDropDownHost.FinishClose describe the two independent gates accurately.
  • No dead accessor remains, and the AC2 producer side has an automated test.

Actual Behavior

  • QfcFormController.Deactivate.cs line 118 gates both callers of ParkFocusAndCancelSelectors; from ActionCancelAsync stage park-focus (QfcFormController.EventHandlers.cs line 144) the predicate degenerates to "is any popup open?" and the stage is skipped. Mitigation exists later via QfcCollectionController.Cleanup -> QfcItemController.Cleanup -> ItemViewer.ResetBreadcrumb -> BreadcrumbDropDownOpenCoordinator.Reset, but through PostAsync, so the ordering guarantee the teardown was written to provide is weakened.
  • IsCommitPending (BreadcrumbDropDownHost.Open.cs 102-107) is cleared only by ShowPopup; RestoreAfterOpenFailure (BreadcrumbDropDownHost.cs line 455) calls FinishClose(Uncommitted) unconditionally and can consume a previous lifetime's latch.
  • BreadcrumbDropDownHost.cs line 450 still says "only the focus step is gated; the cancel step above always runs", contradicted by the gate at line 447.
  • QfcItemController.EventHandlers.cs line 209 SearchOwnsDropDownDismissal has no reader (the underlying field is the live AC4 latch).

Logs / Screenshots

Impact / Severity

  • Blocker
  • High
  • Medium
  • Low

CR-3 is rated Major/latent by the reviewer: the class documentation states that no breadcrumb popup may stay open after teardown or WinForms modal menu mode keeps redirecting keyboard messages to the popup, which is the #677 keyboard-lock class. The remaining items are minor but sit in the same files and should ship together.

Source

From: docs/features/potential/2026-09-07-quickfiler-dropdown-796-post-merge-review-residuals.md

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions