* Support Value pattern on editable ComboBox automation peer
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Add CalendarDayButtonAutomationPeer with SelectionItem pattern
* Guard day button selection against None mode and blackout days, add peer tests
* Use NotNullWhen instead of null-forgiving out parameter
* Implement IToggleProvider on MenuItemAutomationPeer
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Add failing test for cursor when pointer changes
* Introduce PresentationSource.CursorElement
* Update cursor on capture change
* Set correct cursor when capture is released
* Recompute pointer-over element immediately when capture changes
* 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.
* add failing test for RenderTargetBitmap_DropShadowEffect
* Fix immidiateRenderer with Effect wasn't working as expected
* yet another render test
* XML comments for newly added members
* Address Copilot review
* Add another unit test to ensure the recent changes
don't get lost at some point in time
* address review
* Apply Review suggestion
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* inline effectPadding
* implement feedback for better bounds handling
* Update src/Avalonia.Base/Media/DrawingGroup.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* anohter minor fix
* Address PR #20790 review comments
- Fix RenderDataEffectNode.Bounds to return null when no children exist,
preventing empty effect nodes from incorrectly reporting non-null bounds
and causing render artifacts due to incorrect dirty rects.
Bounds now inflates child bounds by the effect output padding rather
than unioning with BoundsRect.
- Move effect output padding inflation from callers into DrawingContext
implementations (PlatformDrawingContext, RenderDataDrawingContext) so
callers pass content bounds to PushEffect and the API handles inflation
internally. Remove pre-inflation from ImmediateRenderer.
- Fix DrawingGroup.DrawCore to pass effectBounds (inflated) to
PushOpacityMask when an Effect is set, so the opacity mask covers
the full effect output region (e.g. shadow/blur extending beyond
visual bounds).
- Fix DrawingGroup.GetBounds to inflate EffectBounds (which now stores
content bounds) by the effect output padding.
- Fix existing compile error: Rect.IsEmpty() is a method, not property.
- Add failing tests for each of the above before fixing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix DrawingGroup.GetBounds() incorrectly inflating bounds with effect output padding
GetBounds() should return content/geometric bounds only, matching WPF behavior.
Inflating by GetEffectOutputPadding() caused DrawingImage to shift its coordinate
origin by the effect's extent (e.g. a 3.5px shadow offset would displace all
content by 3.5px), breaking Should_Render_DrawingGroup_With_Effect render test.
Effects render additively outside the content area and must not affect the
coordinate system established by GetBounds().
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* [Automation] Add EmbeddableControlRootAutomationPeer tests
* [Automation] Implement IRootProvider on EmbeddableControlRootAutomationPeer
Without IRootProvider, AutomationNode.Create falls back to the plain
AutomationNode which doesn't implement IRawElementProviderFragmentRoot
and returns null from GetHostRawElementProvider. As a result,
UiaReturnRawElementProvider responds with E_FAIL for the WM_GETOBJECT
sent to the embedded HWND, and the Avalonia automation tree is invisible
to UIA clients (Inspect.exe, Narrator, FlaUI etc.) when the control is
hosted via WinFormsAvaloniaControlHost.
* Add new CDPicker props for custom text conversion
* Use TextConverter if not null for date parsing
* Fix comment on CustomDateFormatString
* Add unit test for custom date parsing
* CDPicker: When text set ensure right format
* Add test for invalid date input
* Fix failure on new test for invalid date input
* Swap Convert and ConvertBack
See review comment: https://github.com/AvaloniaUI/Avalonia/pull/21193#discussion_r3265891798
* Add failing test for TextConverter.Convert
* Tweak Convert test based on InvokeAsync used in prop update
* Use TextConverter if avail in DateTimeToString
https://github.com/AvaloniaUI/Avalonia/pull/21193#discussion_r3265887941
* Add clarifying comment
* Rename converter for clarity
* Fix failing tests due to DateTimeToString change
* Update docs for CalendarDatePicker.TextConverter
https://github.com/AvaloniaUI/Avalonia/pull/21193#discussion_r3265904591
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add missing AutomationPeers from built-in Controls.
* revert native menu bar peers
* Add back a thin automation peer for native menu bar.
* Use ColorChanged for ColorSpectrumAutomationPeer
* Fix NativeMenuBar/ColorSpectrum automation peer regressions
Flatten MenuItem children under NativeMenuBarAutomationPeer and raise ColorChanged when Color is set directly so ColorSpectrumAutomationPeer notifies AT clients.
* Drop NativeMenuBarAutomationPeer.GetChildrenCore override
Bisect confirmed this override caused 5 Windows IT tests (Slider, Screen, DragDrop) to fail by producing an inconsistent UIA tree where MenuItem peers list NativeMenuBar as parent while their visual parent is the inner Menu. Reverted to the thin peer that only reports ControlType=MenuBar, and dropped the now-irrelevant children assertion test.
AutomationElementIdentifiers.AutomationIdProperty was missing, so
runtime changes to AutomationProperties.AutomationId never raised
UIA_AutomationPropertyChangedEventId on Windows (or the equivalent
on macOS). UIA clients that subscribe to property changes would
silently receive stale automation IDs.
- Add AutomationIdProperty sentinel to AutomationElementIdentifiers
- Raise the event in ControlAutomationPeer.OwnerPropertyChanged
when AutomationProperties.AutomationIdProperty changes
- Add AutomationIdProperty -> UiaPropertyId.AutomationId to the Win32
AutomationNode.s_propertyMap
- Add AutomationPeer_AutomationId to AvnAutomationProperty (avn.idl)
and wire it in AvnAutomationPeer.s_propertyMap and automation.mm
- Add unit tests covering runtime AutomationId change notifications
* ensure system back event is passed to child page once
* fix formatting in DrawerPage
* add tests
* add back default page handler for system back event, but only check OnSystemBackButtonPressed
* removed `OnSystemBackButtonPressed` checks in derived page classes
* nav page - send back event to current page before modal pages.
* Fix modal-first system back routing in NavigationPage
---------
Co-authored-by: Javier Suárez Ruiz <javiersuarezruiz@hotmail.com>
* fix safe area calcs for navigation page
* update nav bar effective height on safe area change
* reset nav bar height if visibility changes
* add tests
* fix: focus correct date selector for day-first locales in DatePickerPresenter
SetInitialFocus had a copy-paste bug where the day-first branch
focused _monthSelector instead of _daySelector. This caused every
locale that puts day first (UK, Europe, Australia, India — dd/MM/yyyy)
to focus the wrong selector when the picker opened.
Refactored the three near-identical if/else branches into a
data-driven loop that pairs each host panel with its selector,
making this class of copy-paste bug structurally impossible.
* chore: retrigger CI
* chore: retrigger CI
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* wip touch improvement textbox
* update text selection handle style
* change text selector layer z-index
* fix build issues
* fix caret detection in touch mode
* added bottom padding to text handle
* add indicator visual to selection handler theme
* improve text selector indicator handling
* add support for wrap around in selection handles
* ensure textbox context menu is shown on hold
* dampen scroll inertia
* increase default tap and double tap sizes for touch and pen
* make textbox context menu horizontal in touch mode. improve context menu show behavior for selection handles
* detect overscroll in scroll presenter and handle scroll gesture if overscrolled
* add rtl detection for selection handles
* improve context flyout behavior in handles
* restore textbox page
* addressed review
* add touch tests textbox
* keep dragged handle visible, adjust flyout position to visible handle
* Introduced "forced" CSD mode without app opting in
* C is for Consistency
* api diff
* [X11] Better handling of forced-vs-app-triggeed CSD
* Round WindowDrawnDecorations sizes to be pixel-aligned
* Split source and target controls in Should_Apply_Design_Mode_Properties_From_Control_To_Window test
* Fix invalid binding being applied
* Use indexer bindings, avoid bind to observable
* Make Window.WindowState a direct property with (on some platforms) reliable values
* Use reported window state from the callback
* compile
* Actually use the cached value in WindowState getter
* api diff
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Tests for our erratic WindowState behavior.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Make FlyoutBase.IsOpen a public StyledProperty with two-way binding support
Convert IsOpen from a DirectProperty with a protected setter to a
StyledProperty with a public setter and TwoWay default binding mode.
This enables MVVM scenarios where a ViewModel can control flyout
visibility through data binding.
The implementation mirrors the established Popup.IsOpen pattern:
- Reentrancy guard (BeginIgnoringIsOpen scope) prevents recursive
property change notifications when internal code syncs the property
- SetCurrentValue preserves active bindings and styles (enforced by
analyzer AVP1012)
- _isOpen field tracks actual open state independently of the property
value, since the property system sets the value before the change
handler fires
- _lastPlacementTarget enables re-opening at the last known target
when IsOpen is set to true via binding
- IsOpen reverts to false when no target is available or opening is
cancelled, and reverts to true when closing is cancelled, keeping
the property honest
Fixes#18716
* ci: retrigger checks
* Add API suppression for FlyoutBase.IsOpenProperty type change
Suppress CP0002 for the intentional binary breaking change from
DirectProperty<FlyoutBase, bool> to StyledProperty<bool>.
* Pre-register owning control as flyout placement target
When Button.Flyout or SplitButton.Flyout is set, the owning control
now registers itself as the default placement target via an internal
SetDefaultPlacementTarget method. This allows IsOpen = true to work
on first use without a prior ShowAt call, addressing review feedback
from MrJul.
* Remove TwoWay default binding mode from IsOpenProperty
Follow Avalonia convention: Popup.IsOpen and ToolTip.IsOpen use the
default OneWay binding mode. TwoWay is reserved for input controls.
Users opt in with Mode=TwoWay when needed.
* 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>
* test: verify ShowCore applies default icon when no custom icon is set
Adds a test that verifies Window.Show() applies the default icon via
SetIcon when no custom icon has been set. Currently fails because
ShowCore has no default icon logic — the fallback only exists in the
constructor binding where it eagerly loads the icon.
Relates to #20478
* fix: defer default icon loading from constructor to ShowCore
The default icon was eagerly loaded during Window construction via
CreatePlatformImplBinding, even when a custom icon would be set or no
icon was needed. This caused unnecessary I/O (assembly resource loading)
on every first Window instantiation.
Move the default icon fallback from the binding lambda to ShowCore,
so LoadDefaultIcon only runs when the window is actually shown and
no custom icon has been set.
Fixes#20478