* Added failng popup child margin test
* Ignore popup child margin when positioning
Avoids drop shadows and other out-of-bounds visual effects from affecting popup positioning
* Fix warnings in tests
* Pass Deflate to WSurface
---------
Co-authored-by: Tom Edwards <tom.edwards@chaos.com>
* Add failing test for #7536
Reproduces the "Cannot change source while update is in progress" crash that
occurs when a SelectingItemsControl's ItemsSource is changed from within its own
SelectionChanged handler while the selection is being lost. When selection is
lost, CommitOperation bumps the operation UpdateCount before raising
LostSelection but never decrements it, so SelectionChanged is raised with
UpdateCount > 0 and SetSource throws.
Claude-Session: https://claude.ai/code/session_01FXP1ejZ9VhUwecY9QCRKVb
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Fix#7536: crash when changing source during SelectionChanged
When the selection was lost, SelectionModel.CommitOperation incremented the
operation's UpdateCount before raising LostSelection but never decremented it.
As a result the rest of the commit - including the SelectionChanged event - ran
with UpdateCount > 0, so a handler that changed the control's source (as
StructuredLogViewer's UpdateBreadcrumb does) hit the "Cannot change source while
update is in progress." guard in SetSource and threw.
Decrement UpdateCount again once the LostSelection handler has returned so that
the batching only covers the handler itself and the SelectionChanged event is
free to change the source.
Claude-Session: https://claude.ai/code/session_01FXP1ejZ9VhUwecY9QCRKVb
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Add test for changing selection from SelectionChanged when AlwaysSelected reselects
Covers the interaction between the #7536 fix and AlwaysSelected: clearing the
selection makes AlwaysSelected reselect the first item via LostSelection (which
must still fold into the current operation), and a SelectionChanged handler that
then changes the selection must be honoured rather than swallowed by the batch
update wrapping the LostSelection handler. Fails before the fix (selection stays
on the reselected item), passes after.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXP1ejZ9VhUwecY9QCRKVb
* Assert that `SelectionChanged` was called.
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* Add BringIntoView pass to the LayoutManager
* Make ProcessBringIntoViewRequests part of the standard layout pass
* Clarify why TryScrollIntoViewNow's result is ignored
---------
Co-authored-by: grokys <grokys@users.noreply.github.com>
* fix: light dismiss behavior fails when opened from the ContextMenu.
* 1. LightDismissOverlayLayer is invisible by default.
2. Eliminate misinformation that Registration may bring.
3. Remove LightDismissOverlayLayer Manually set IsVisible to false at creation time.
---------
Co-authored-by: Steven Kirk <grokys@users.noreply.github.com>
* Implement TopLevel.OpenedPopups
* Delete Headless `GetOpenPopups`
* Reorganize popup tests between Headless/Primitives layers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Add Popup.OpenedPopups to keep opened popups in tree structure
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Help NUnit suppressing CS8777
* Update suppresions
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* Add failing test for #14718
* Fix for AutoScrollToSelectedItemIfNecessary
* fix failing CI build and move test to the right location
* add failing test for TabItem selection of invisble tab
* introduce a helper method to figure out which item to select
when nothing was selected beforehand and AlwaysSelected is true
* ensure selection works for invisible tabcontrol
* simplify conditions
* propose: Remove redundant logic from ColorView
The TabItem now handles the correct selection of only visible items
* fix test: Need to set SelectedIndex after adding items
* re-add unused method and make it obsolete
Otherwise API-diff will fail.
* Address review
* Update tests/Avalonia.Controls.UnitTests/TabControlTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update tests/Avalonia.Controls.UnitTests/TabControlTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Adress copilot review
* fix duplicate braces
* address review
* fix for failing tests on CarouselPage and TabbedPage
* address feedback
- adding more tests to avoid regressions
* Fix failing test: add UnitTestApplication.Start() to dedicated thread test
Agent-Logs-Url: https://github.com/timunie/Avalonia/sessions/fe2f1190-6d20-4982-8a03-1ae9b52ee701
Co-authored-by: timunie <47110241+timunie@users.noreply.github.com>
* Refactor SelectingItemsControl auto-scroll duplicate logic
Agent-Logs-Url: https://github.com/timunie/Avalonia/sessions/8895cb60-ef41-473c-972b-bad2483a5a77
Co-authored-by: timunie <47110241+timunie@users.noreply.github.com>
* Add new failing tests for AlwaysSelected mode
* Fix AlwaysSelected scenarios
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* fix(ScrollBar): use large scroll events for ScrollToHome and ScrollToEnd
* Fix failing test
---------
Co-authored-by: Tim <47110241+timunie@users.noreply.github.com>
* fix: raise SelectionChanged event on collection Reset when items are deselected
When a collection bound to a SelectingItemsControl (e.g. ListBox) was
cleared via NotifyCollectionChangedAction.Reset, the SelectionChanged
event was not raised despite the selection being lost.
The root cause was in InternalSelectionModel.OnSourceReset: the base
SelectionModel.OnSourceReset() directly reset _selectedIndex to -1
before any Operation could capture the old selection state. The
subsequent SyncFromSelectedItems created an Operation that saw no
change (old and new both -1), so CommitOperation never fired
SelectionChanged.
The fix snapshots _writableSelectedItems before sync, diffs against
the post-sync state to find items that were actually lost (not merely
re-selected at a new index after reorder), and injects them as
DeselectedItems on the pending Operation — following the same pattern
used by OnSelectionRemoved for individual item removals.
Fixes#20897
* fix: use multiset diff to report lost duplicate selections on Reset
The Reset diff in InternalSelectionModel used a HashSet to detect
which previously-selected items were still present after sync. Selection
allows duplicates (same instance or equal items at multiple indices),
so set semantics collapsed duplicates into one entry and under-reported
deselections when only some occurrences were lost.
Track counts per item plus a null counter and decrement per match, so
RemovedItems reflects the actual number of lost selections.
Adds a duplicate-items Reset test covering the regression.
* fix: raise SelectionChanged for reset-lost selection
ListBox and other SelectingItemsControl callers did not receive SelectionChanged when a Reset cleared the selected items. The selection model reports this path through LostSelection, but the control only used that callback for AlwaysSelected recovery.
Track the last selected items at the control boundary, capture that snapshot for Reset notifications, and raise the routed SelectionChanged event when LostSelection commits during that reset. This avoids diffing reset contents while preserving the removed-items payload for clear/reset-to-empty cases.
* fix: address review feedback on SelectionChanged Reset snapshot
- Replace per-change ToArray() snapshot with persistent List<object?> to
avoid allocations on every selection change (review: MrJul).
- Read snapshot in PreCollectionChanged instead of Selection.SelectedItems
because the source is already empty by the time Reset fires.
- Align LostSelection event-raising with SelectionChanged path: use
BuildEventRoute + HasHandlers guard to avoid allocating args when
no handlers are attached (review: copilot).
- Harden existing Reset tests to Assert.Single to catch double-fire.
* fix: consolidate SelectionChanged raising and defend against stale snapshot
- Extract RaiseSelectionChanged helper so both the normal
(SelectionChanged) and reset (LostSelection) paths share the same
BuildEventRoute/HasHandlers guard and SelectionChangedEventArgs
construction (review: copilot).
- Move _selectedItemsBeforeReset clear outside the conditional in
OnSelectionModelLostSelection so the field is always nulled after
LostSelection, preventing accidental reuse (review: copilot).
- Add comment documenting the snapshot lifecycle in
OnItemsViewPreCollectionChanged.
* perf: defer SelectionChangedEventArgs allocations until handlers are confirmed
SelectionChangedEventArgs materialized arrays via ToArray() at the call site
before checking whether the routed event had any registered handlers. This
allocated needlessly in the common case of no external subscribers.
The event items (IReadOnlyList<object?>) already implement IList via
ReadOnlySelectionListBase. RaiseSelectionChanged now accepts
IReadOnlyList<object?> and casts to IList inside the HasHandlers gate,
falling back to ToArray() only for non-IList enumerables.
* refactor: Replace IsPopup with Enable*Layer properties on VisualLayerManager
- Remove IsPopup from VisualLayerManager, add granular Enable*Layer properties:
EnableAdornerLayer (default true), EnableOverlayLayer (default false),
EnablePopupOverlayLayer (internal, default false), EnableTextSelectorLayer (default false)
- Add PART_VisualLayerManager template part to TopLevel with protected property
- Window and EmbeddableControlRoot override OnApplyTemplate to enable
overlay, popup overlay, and text selector layers
- OverlayLayer is now wrapped in a Panel with a dedicated AdornerLayer sibling
- AdornerLayer.GetAdornerLayer checks for OverlayLayer's dedicated AdornerLayer
- Update all 8 XAML templates (both themes) to name PART_VisualLayerManager
and remove IsPopup="True" from PopupRoot/OverlayPopupHost
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add XML doc to VisualLayerManager
* Also search for AdornerLayer from TopLevel
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Make some overlay-related types/members internal
* Make sure that TopLevel is no longer the actual root of the visual tree. This is needed for our future changes.
* API diff
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fixed incorrect test
* Make automation to target FocusRoot
* api diff
* Hide WindowBase/EmbeddableControlRoot's parents from automation
* api diff
* Separate automation root and visual root for automation purposes
* Hide ChromeOverlayLayer from public API
* Synchronize WindowBase visibility to VisualRoot
* Hide WindowBase.ArrangeSetBounds
* api diff
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Extracted IInputRoot out of TopLevel
* Move some input handling out of TopLevel
* Remove old class, make layout manager private
* Removed IRenderRoot
* Make VisualTreeAttachmentEventArgs a bit more sensible
* Move ILayoutRoot to PresentationSource
# Conflicts:
# tests/Avalonia.Controls.UnitTests/TabControlTests.cs
* Updated some VisualRoot / GetVisualRoot usages
* Updated more XxxRoot usages
* More Root usages
* Addressed review
* Hurr-durr xml
* More fixes
* Maybe fix android compilation
* API diff
* Yet another cast
* I had to use MSIL analysis to detect those casts
* Fixed automation
* Fix PointerOverPreProcessor
* Fix?
* Removed yet another cast to Visual
* The amount of random downcasts is astonishing
* Maybe fix mac
* Addressed review
* Introduce a universal IGlyphTypeface implementation that does not rely on any platform implementation
* Revert changes
* Fix Android
* Make the test happy
* Fix build
* Update baseline
* Fix naming
* Fix headless
* Move interfaces to dedicated files
Make GlyphTypeface.GlyphCount an integer
* Fix GlyphCount
* Make IGlyphTypeface NotClientImplementable
* Make sure we cache platform typefaces by their desired name, style, weight and stretch
* Update baseline
* Only use IGlyphTypeface
* Fix Android
* Try to clear the buffer before we encode somethimg
* Add needed test font
* Add more unit tests
* Reduce allocations
* Remove Direct2D1 test files
* More tests
* More complete table implementations
* More adjustments
* Use batch APIs
* Handle invalid timestamps
* Update baseline
* Introduce a CharacterToGlyphMap struct for faster access
* Remove AggressiveInlining
* Remove AggressiveInlining
* Make the head table optional for legacy fonts
* Remove Load method. Fix TextBlockTests
* Fix nullables
* Remove redundant folder
* Update Api baseline
* revert diff helper changes
* revert changes
* Use bare minimum font for Headless platform and introduce a test font manager that uses the Inter font for testing.
* Add missing font file for Headless platform
---------
Co-authored-by: Gillibald <stebner@avaloniaui.net>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Update to xunit.v3
* Little more progress
* More fixes
* Keep VSTest supported
* Adjust Nuke
* Few fixes
* Fix for xunit 2
* Fix GetData override
* Adjust
* Use MTP for xunit 2
* Fix test
* Better fix
* --no-progress
* Few more fixes
* no progress
* Fix test
* Better fix
* TRX
* Move to Directory.Build.props
* Unify on MTP v2
* Update
* Update to stable
* 1.0.1
* 1.0.2
* Fix some warnings
* Fix more warnings
* Fix more warnings
* Implement layout rounding for child sizes
Added layout rounding for child measurements in UniformGrid.
* Remove comment on child measurement in UniformGrid
Removed comment about measuring children in UniformGrid.
* Improved layout rounding logic for UniformGrid
* Grid_Ensures_Consistent_Cell_Width_When_UseLayoutRounding
* Improve FontCollection user story
* Make adjustments after review
* Refactor IsFontFile
* Make FontFamilyLoader internal
Make tests happy again
* Update baseline
* Adjust modifier
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add UniformGrid test cases for scenarios where row/column spacing takes more than available space
* Constrain child size to non-negative when performing arrange in UniformGrid
* Add failing tests for SelectedItem/SelectedIndex without an ItemsSource
* Keep SelectedItem/SelectedIndex until ItemsSource is set
* Add failing tests for setting SelectedValue without an ItemsSource
* Keep SelectedValue until ItemsSource is set
* Add failing focus tests for flyouts inside overlay popups
* Implement IKeyboardNavigationHandler on OverlayPopupHost
* Layout OverlayPopupHost content for focus to work
* Add CustomPopupPlacement API
* Add Placement="Custom" support for Flyout, ToolTip and ContextMenu controls as well
* Adjust some API changes
* Add Avalonia.Controls.Primitives.IPopupHost.ConfigurePosition breaking change
* Extract new types into separated files
* Fix build after merge conflict
* Adjust nupkg.xml
* Dispose property subscriptions after popup is closed, avoiding flickering
* Adjust API to be more future proof and add new parameters.
* Add new ContextRequestedEventArgs overload while I am on it
* Add Popup.SetPopupParent helper method
* Update Tooltip to use Popup internally instead of PopupRoot
* Mark OverlayPopupHost.CreatePopupHost as unstable method
* Close tooltip when popup is closed
* Fix popups not closing when target is detached
* Remove unrelated change
* Added failing tests for #12733.
* Clear SkipLostSelection on batch update start.
If `Source` is changed during a collection update, then the `Clear()` operation will not be committed immediately due to `_isSourceCollectionChanging` being set. In this case, `update.Operation` will still have `SkipLostSelection == true`, meaning that `LostSelection` will not be raised, causing #12733. Clear the flag manually each time `BeginBatchUpdate` is called to avoid this.
Fixes#12733
---------
Co-authored-by: Max Katz <maxkatz6@outlook.com>
* Init
* Remove XY navigation cache as it's no use
* Use pooled collection for XY navigation
* Restructure code a bit, fix IScroller handling
* Init KeyboardNavigationTests_XY tests
* Simplify XYFocus.GetNextFocusableElement usage
* Minor fixes
* Add more tests
* Remove unused NuiKeyboardNavigationHandler
* Finalizing
* Fix tests
* Add TODO12
* Make XYFocusOptions a class
* Add TestServices.FocusableWindow and make KeyboardNavigationHandler lazy, as it can't be reused on multiple windows
* Fix KeyboardNavigationHandler events handling, when focus was not actually changed
* Add arrow key tests
* Replace XYFocusKeyboardNavigationMode with more flexible XYFocusNavigationModes, integrate with KeyDeviceType input types
* Make XY focus navigation less broken, when there is no starting focused control
* Several Android TV compatibility improvements
* Remap tizen Back button to Esc
* Introduce internal XYFocusHelpers
* Make ComboBox and AutoCompleteBox handle Key events only when it's needed
* Make TextBox handle Key events only when it's needed
* Ignore Alt+Down when XY navigation is enabled in CalendarDatePicker and SplitButton
* Rename IsAllowedXYNavigationMode
* Fix ButtonSpinner with XY navigation
* Implement a very simple focus engagement for GridSplitter and Slider
* Add an item with null values to the SelectingItemsControl test data
* Fixed NullReferenceException when SelectedValueBinding evulates to null
Fixed SelectedValue bindings being overwritten when a new item is selected
* Add SelectingItemsControl property init order tests
* Property order in SelectedItemsControl doesn't matter on init
* Fix SelectedItemsControl properties during init when Selection is set
* Fixed SelectedItemsControl.AnchorIndex after init
* Add failing test for RangeBase overriding Value on DataContext changed
* Add bool flag to skip coercing min, max and value while DataContext is
changing
* Add failing unit test for scenario 1 in #11878.
* Set TabOnceActiveElement on realized container.
Fixes scenario 1 in #11878.
* Use TabOnceActiveElement to decide focused element.
Fixes scenario #3 in #11878.
* Remove focus hack from Popup.
* Added failing focus scope tests.
* Refactor focus scopes in FocusManager.
- Store focused element within a scope using an attached property (like WPF)
- Store current focus root so that focus can be restored to that root when a focused control or active focus scope is removed
Fixes#13325
* Suppress API compat error.
This was being produced for a compiler-generated enumerable class that was erroneously being included in the reference assembly for `FocusManager`.
* Remove focus hack from ContextMenu.
And add failing test now that the hack is removed.
* Try to return a rooted host visual.
Fixes failing test from previous comment where focus wasn't restored when closing a context menu.