Skip to content

Global Dock Tracking, Overlay Context Resolution#1029

Merged
wieslawsoltes merged 6 commits intomasterfrom
feature/issue-1023-global-tracking
Feb 7, 2026
Merged

Global Dock Tracking, Overlay Context Resolution#1029
wieslawsoltes merged 6 commits intomasterfrom
feature/issue-1023-global-tracking

Conversation

@wieslawsoltes
Copy link
Copy Markdown
Owner

@wieslawsoltes wieslawsoltes commented Feb 7, 2026

PR Summary: Global Dock Tracking, Overlay Context Resolution, Samples, and Test Coverage

Linked Issue

Goal

Implement proper global tracking events/state across multi-root/multi-window layouts, align behavior with expected focus/activation semantics, expose this in MVVM/ReactiveUI samples via status bar updates, improve overlay service targeting for busy/dialog positioning, and provide broad test coverage.

What Changed

1. Core Global Tracking Model and API

Introduced first-class global tracking state in IFactory and wired it through FactoryBase:

  • New state object:
    • GlobalDockTrackingState (Dockable, RootDock, Window, HostWindow)
  • New reason enum:
    • DockTrackingChangeReason
  • New event args:
    • GlobalDockTrackingChangedEventArgs
  • New factory API surface:
    • IFactory.GlobalDockTrackingState
    • IFactory.CurrentDockable
    • IFactory.CurrentRootDock
    • IFactory.CurrentDockWindow
    • IFactory.CurrentHostWindow
    • IFactory.GlobalDockTrackingChanged

2. Event Context Enrichment

Expanded focus/active event args to include window/root ownership context:

  • ActiveDockableChangedEventArgs now includes:
    • RootDock, Window, HostWindow
  • FocusedDockableChangedEventArgs now includes:
    • RootDock, Window, HostWindow

3. Factory Tracking Behavior (Expected Semantics)

Implemented and refined global tracking transitions in FactoryBase:

  • Tracking updates on:
    • OnWindowActivated
    • OnDockableActivated
    • OnFocusedDockableChanged
    • OnActiveDockableChanged
  • Tracking clears on tracked-window lifecycle:
    • OnWindowDeactivated
    • OnWindowClosed
    • OnWindowRemoved
  • Deactivation fallback behavior:
    • OnDockableDeactivated moves to focused/active fallback when available.

Important correctness guards (review-driven)

To prevent background roots from overriding global context:

  • OnActiveDockableChanged only updates global state when source root matches tracked root (or when nothing tracked yet).
  • OnFocusedDockableChanged same guard as above.
  • OnDockableActivated now uses the same root ownership guard (critical fix from review).
  • Null active/focus notifications re-anchor to current tracked root context instead of destructive clearing.

4. FactoryExtensions Behavior

Updated helper behavior to prefer global tracking first:

  • GetActiveRoot() uses CurrentRootDock before legacy scan.
  • GetCurrentDocument() uses CurrentDockable fallback.
  • CloseFocusedDockable() prefers globally tracked dockable.
  • Exposed helpers:
    • GetCurrentDockWindow()
    • GetCurrentHostWindow()

5. Overlay Services API Improvement

Improved overlay lookup API so overlays resolve by dockable context (window-aware) rather than only host screen fallback:

  • IHostOverlayServicesProvider new overload:
    • GetServices(IScreen screen, IDockable dockable)
  • HostOverlayServicesProvider now resolves via dockable/owner/root/window path before fallback.
  • Added dockable-aware helpers in DockNavigationHelpers:
    • GetOverlayServices(...)
    • GetBusyService(...)
    • GetDialogService(...)
    • GetConfirmationService(...)
  • Updated RoutableDocumentBase and RoutableToolBase to use dockable-aware overlay resolution.

6. Sample UX Updates (Status Bar)

Added global tracking status display in:

  • samples/DockMvvmSample
  • samples/DockReactiveUISample

Both now:

  • Subscribe to GlobalDockTrackingChanged
  • Display a formatted global tracking status line with dockable/root/window/host info
  • Include enriched debug logs for focus/active/global transitions

7. Documentation

Added and updated docs to reflect the new model and behavior:

  • New article:
    • docfx/articles/dock-global-tracking.md
  • Updated:
    • dock-events.md
    • dock-active-document.md
    • dock-overlay-services-reference.md
    • dock-api-scenarios.md
    • toc.yml

Testing

Existing multi-variant factory tests updated

Extended factory tests in all model variants:

  • Dock.Model.Mvvm.UnitTests
  • Dock.Model.ReactiveUI.UnitTests
  • Dock.Model.Prism.UnitTests
  • Dock.Model.ReactiveProperty.UnitTests
  • Dock.Model.Avalonia.UnitTests

Coverage includes:

  • Root/window context on event args
  • Global tracking updates and clears
  • Guard behavior for cross-root interference
  • Null handling / non-destructive behavior
  • SetActiveDockable cross-root override prevention

New exhaustive tracking matrix tests

Added dedicated test suite:

  • tests/Dock.Model.Mvvm.UnitTests/GlobalDockTrackingTests.cs

Covers all tracked transitions and reasons, including:

  • Each DockTrackingChangeReason
  • Non-tracked no-op paths
  • Duplicate update suppression
  • Window close/remove/deactivate tracked vs non-tracked
  • Dockable deactivation fallback permutations
  • Host window propagation

New headless integration tests

Added:

  • tests/Dock.Avalonia.HeadlessTests/GlobalDockTrackingTests.cs

Validates runtime/managed-window behavior:

  • Active managed-window switching reason sequence
  • Guarded behavior against background SetActiveDockable
  • Null active managed window clearing behavior

Leak regression fix after CI review

Addressed leak-test failures caused by global tracking retaining strong references during unresolved-root initialization paths:

  • GlobalDockTrackingState now stores weak references for tracked dockable/root/window.
  • Global tracking updates from:
    • OnActiveDockableChanged
    • OnFocusedDockableChanged
    • OnDockableActivated
      now require a resolved root (ResolveRootDock(...) != null).
  • Window-based tracking clear now also clears by tracked root/layout match, not only by exact tracked window instance.
  • Added regression assertions:
    • ActiveDockableChanged_With_Unresolved_Root_Does_Not_Change_State
    • DockableActivated_With_Unresolved_Root_Does_Not_Change_State
      in tests/Dock.Model.Mvvm.UnitTests/GlobalDockTrackingTests.cs

Validation Run (latest)

  • dotnet test Dock.slnx --nologo
    • Passed (no failures)
    • Leak suites were skipped where configured
    • Existing nullable warnings remain in unrelated areas (CS8601, CS8603)
  • dotnet test -c Release tests/Dock.Avalonia.LeakTests/Dock.Avalonia.LeakTests.csproj --nologo
    • Passed (115 passed, 0 failed, 0 skipped)

Commit Breakdown (granular)

  1. 0997df491 - Add global dock tracking state and guarded factory updates
  2. c43f26347 - Improve overlay service resolution using dockable context
  3. 91285bc33 - Document global tracking and surface it in samples
  4. 3e1de0435 - Add factory tests for global tracking across model variants
  5. 183e72e1c - Add exhaustive global tracking unit and headless tests
  6. 3dfc466ef - Fix global tracking retention causing leak-test regressions

Notes for Reviewers

  • The main behavioral guarantee is: global context follows tracked active root/window and is protected from background-root overrides.
  • Overlay resolution changes are additive but include an interface extension; consumers with custom IHostOverlayServicesProvider implementations must implement the new overload.

Fixes #1023

@wieslawsoltes wieslawsoltes merged commit cb37784 into master Feb 7, 2026
9 checks passed
@wieslawsoltes wieslawsoltes deleted the feature/issue-1023-global-tracking branch February 7, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global active/focused document tracking with floating windows: no reliable way using ActiveDockableChanged / FocusedDockableChanged

1 participant