Conversation
* replace hamburger view with drawer page. use ContentPage in control catalog * Added Icons * fix listbox and carousel page * make MainView drawer page * add PageNavigationHost to control catalog --------- Co-authored-by: Javier Suárez Ruiz <javiersuarezruiz@hotmail.com>
* test: add DataFormat.CreateInProcessFormat tests Cover the new InProcess format API: kind, identifier, null/empty validation, non-ASCII identifiers, HasSystemName for all four kinds, ToSystemName throwing, equality/inequality, DataTransferItem integration, and coexistence with other formats in DataTransfer. * feat: implement DataFormat.CreateInProcessFormat<T> for in-process drag/drop Add DataFormatKind.InProcess and DataFormat.CreateInProcessFormat<T>() so users can pass arbitrary object references during in-process drag-and-drop without crossing serialization boundaries. - Add HasSystemName property to indicate whether ToSystemName() is valid - Update ToSystemName to throw for InProcess (same as Universal) - Guard all 7 platform backends (Win32, macOS, X11, Android, Browser, iOS) to skip InProcess formats during clipboard/drag-drop enumeration Closes AvaloniaUI#20097 * fix: remove HasSystemName API per review feedback
* fix: correct null check variable in TryResolveFileReferenceUri on macOS The null check on line 401 tested `fileUri` instead of `filePathUri`, making it dead code since `fileUri` was already checked on line 394. When `[fileUri filePathURL]` returned nil (non-file URL or unreachable resource), the nil `filePathUri` was passed to `[filePathUri absoluteString]` and then to `CreateAvnString`, causing a native crash. * fix: initialize NSError to nil in SaveBookmarkToBytes on macOS NSError* was declared without initialization, containing stack garbage. On the success path (bookmarkData non-nil), Cocoa does not guarantee zeroing the error out-parameter, so the subsequent `if (error != nil)` check could read garbage and incorrectly call CreateAvnString with a garbage pointer. Initialize to nil and restructure to `else if` so the error is only inspected when bookmarkData is nil (the failure path). * chore: retrigger CI * fix: guard out-parameters in SaveBookmarkToBytes Initialize *ppv to nullptr on entry so callers never read garbage on the nil-fileUri / nil-bookmarkData paths. Guard *err write with a nullptr check for callers that pass no error out-parameter. * chore: retrigger CI --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
…oniaUI#21114) * fix: check format key in DataTransferItem.FindAccessor single-item path The single-item fast path in FindAccessor returned the stored value for any format query without checking if the requested format matched. This caused TryGetRaw to return wrong data when queried with a format different from the one stored (e.g., querying Bitmap on a text-only item returned the text value instead of null). Add the missing singleItem.Key.Equals(format) check, consistent with the dictionary path (TryGetValue) and RemoveCore. * chore: retrigger CI * chore: retrigger CI --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* add failing test for AvaloniaUI#20008 * fix AutoCompleteBox ignores text changes * Address review comments * Update tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
…AvaloniaUI#21116) * 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>
* Announce changes to live regions on macOS It is necessary to manually request announcement of the new name of a live region, alongside posting the general kAXLiveRegionChangedNotification. * Refactor -raisePropertyChanged: to use switch statement * Fix warning about switch not covering all cases --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add regression test for subtree input hit testing * Fix subtree input hit test coordinates
…ute (AvaloniaUI#21126) * Add failing tests for toggle command gating * Prevent disabled toggle controls from changing state * Rework toggle command gating tests around pointer input * Add touch regression for toggle command gating * Remove synthetic toggle command gating tests
* Fix invalid cast exception in PageNavigationHost * Added tests --------- Co-authored-by: Javier Suárez Ruiz <javiersuarezruiz@hotmail.com>
…valoniaUI#21136) * Win32: fix None/BorderOnly maximized position on secondary screens * Fix WindowCustomizationsPage * Use correct screen when minimized * Fallback to nearest monitor
…d focus is disabled (AvaloniaUI#21168) Removed misleading AI slop test
* fix safe area calc in drawer page * pagenavigationhost - properly clean up scaling change subscription --------- Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
…al change (AvaloniaUI#20964) * Fix AvaloniaUI#20816: OneWay binding fails to update target after local change When a OneWay binding target is modified locally (e.g., via user interaction on a ToggleButton), subsequent PropertyChanged events from the source were being ignored. This occurred because the binding expression incorrectly suppressed the update. This patch modifies UntypedBindingExpressionBase to ensure that OneWay bindings always propagate changes from the source to the target, overriding any previous local changes. Unit tests were also added to prevent future regressions on this behavior. Signed-off-by: Martim Claudino <martimffclaudino@tecnico.ulisboa.pt> * fix: scope forceUpdate to OneWay mode, use SetCurrentValue in tests and clean usings Signed-off-by: Martim Claudino <martimffclaudino@tecnico.ulisboa.pt> --------- Signed-off-by: Martim Claudino <martimffclaudino@tecnico.ulisboa.pt>
* Fix Metal renderer memory leakage on macOS * Remove no-op ResetContext call * Disposable wrapper * Success flag in ctor to dispose * Rename variable name to _autoReleasePool * Abstraction over AutoReleasePool * Use Interlocked.Exchange in AutoReleasePool --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
…loniaUI#21184) * Add back Design.SetPreviewWith(AvaloniaObject, Control) overload * Remove dead code
…#21177) * Add unit tests for decoration hit testing * Fix chrome hit testing * macOS: handle TitleBar element role
* Add failing test: LineBreakEnumerator infinite loop on empty string * Return false immediately for empty string in LineBreakEnumerator Empty text has no content and should not produce any line break opportunities. Short-circuit in MoveNext before entering the read/rule loop, while keeping the PeekAt EndOfText fix as a defensive safeguard.
…1812) Previously {Binding ^} was not parsed because ParseStart did not recognize the ^ stream operator. Also, {Binding .^} failed because ParseDot returned State.End immediately, preventing subsequent operators. Changes: - ParseStart: recognize ^, emit EmptyExpressionNode + StreamNode - ParseDot: return State.AfterMember instead of State.End, so .^ works - Add grammar tests for ^ and .^ patterns
…valoniaUI#21705) * Correct nested TreeViewItem selection behaviour on pointer release * Add unit tests
* feat: add ToolTip.ShouldUseOverlayLayer attached property Add ShouldUseOverlayLayer attached property to ToolTip, which is bound to Popup.ShouldUseOverlayLayer when the tooltip popup is created. This allows per-control control over whether the tooltip popup uses the overlay layer. * docs: add proper XML docs for GetShouldUseOverlayLayer/SetShouldUseOverlayLayer Replace <inheritdoc/> pointing to Popup.ShouldUseOverlayLayer (a property) with proper <summary>, <param>, and <remarks> documentation for the getter and setter methods.
* Add regression test for SimpleTheme focus adorner * Fix SimpleTheme focus adorner in dark mode * Remove redundant focus adorner test
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add regression test for ListBox removal scroll crash * Fix virtualized arrange after collection changes
…1834) * test(textblock): cover fractional layout rounding A wrapped TextBlock with a fractional line height must retain every line when its desired height lands exactly on a fractional-scale pixel boundary. * fix(text): preserve lines at rounded fractional heights TextLayout treated a floating-point accumulation error as a MaxHeight overflow. Use the established tolerant comparison so a line that exactly fits its rounded layout bounds is retained. --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* test(grid): reproduce shared size group shrink failure Shared auto columns expand when grouped content becomes visible but keep the expanded width after that content is hidden. Cover the full zero, expanded, and shrunk layout sequence so the stale shared minimum cannot regress unnoticed. * fix(grid): allow shared size groups to shrink Shared auto definitions reused the previous group minimum while recomputing the next group minimum, so an expanded width became self-sustaining after content shrank. Aggregate each definition's intrinsic measured minimum instead, preserving the shared-size invariant and matching the canonical WPF algorithm. * test(grid): reproduce shared size group stuck on cyclic measure path A grid mixing an auto-column/star-row cell with a star-column/auto-row cell measures through Grid's cyclic dependency path, which saves and restores definition min sizes around the repeated measure. The saved value is the effective min size, so the group minimum is folded into the definition's own contribution and the group can never shrink below it. * fix(grid): restore raw min sizes on the cyclic measure path Grid.CacheMinSizes read DefinitionBase.MinSize, which already includes the shared group's minimum, but ApplyCachedMinSizes writes it back through SetMinSize, which assigns the definition's own _minSize. A short-pole definition therefore adopted the group minimum as its own intrinsic minimum, which reclassified it as a long pole on the next validation. Long poles with a valid measure are never remeasured, so the fabricated minimum became unreachable and pinned the group open. Add DefinitionBase.RawMinSize, the read counterpart of SetMinSize, and cache that instead so the save/restore pair round-trips the definition's own contribution. Matches the WPF fix in dotnet/wpf#2270.
…#21839) * test(TextBox): reproduce stale undo history after binding update TwoWay-bound TextBox instances retain prior user-edit snapshots when the binding source replaces the text, allowing undo to write values from a previous model context back into the current source. Cover the external replacement and the normal TwoWay source echo separately so a fix cannot clear valid user undo history after each edit. * fix(TextBox): reset undo history for external text updates Binding and direct property updates currently enter the same undo timeline as user edits, so a reused TwoWay-bound TextBox can write text from a previous model back into the current source. Track TextBox-initiated mutations through synchronous source notifications, preserve those edits in the undo timeline, and establish a fresh baseline for all external updates. MaskedTextBox routes its own edits through the same boundary so its existing undo behavior remains intact. * fix(TextBox): distinguish edits from internal synchronization in undo history Replace the boolean text-mutation flag with a three-state TextMutationKind (ExternalReplacement / Edit / InternalSynchronization) so MaskedTextBox's prompt-character reformatting on focus/blur and mask-provider refreshes no longer create undo entries, while actual keyboard edits remain undoable.
…d mode if supported. This change ensures proper transparency support for popups when in Vulkan rendering mode. Upon updating to Nvidia driver 610.74, Popups, when in Vulkan rendering, were showing the classic black square around them if margin is applied. This fixes that issue while still falling back if pre-multiplied is unavailable. (AvaloniaUI#21802)
* Force-mark closed window as no longer active if backend didn't do it for some reason * [X11] Speculatively mark the active closed dialog parent as active window
… size group (AvaloniaUI#21848) * test(grid): reproduce shared size groups ignoring assigned definitions Definitions supplied through the ColumnDefinitions or RowDefinitions setter are already in the collection when the grid claims it, so they never pass through the collection-changed handler that joins them to the parent tree. They never register with their shared size group, and the definitions they replace never unregister from it. * fix(grid): join assigned definition collections to the parent tree DefinitionList.SetParent assigned each definition's Parent but never called OnEnterParentTree, which only ran from the collection-changed handler. Assigning Parent is not sufficient: OnEnterParentTree also sets InheritanceParent, and a definition cannot read the inherited PrivateSharedSizeScope that registers it with its group until that link exists. Definitions supplied through the ColumnDefinitions setter - an object initializer, a shared resource, or ColumnDefinitions="Auto,*" - were therefore silently absent from their shared size group. Enter and exit the parent tree from SetParent, and release the outgoing collection when Grid swaps one in. Without that release the replaced definitions stay registered with the group; nothing resets their measured minimum any more, so they pin it at whatever they last contributed. * test(grid): cover the definition ownership contract Removing a definition leaves it holding its old Parent and its property inheritance link, so it still reads the grid's shared size scope and can re-register itself into a scope it has left. Also covers moving a definition between grids, reassigning the same collection, and row definitions, which the assignment fix reached but nothing exercised. * refactor(grid): centralise definition parent-tree transitions Definition ownership was implemented twice, and the two paths disagreed: SetParent exited a definition and cleared its Parent, while removing one from the collection called OnExitParentTree but left Parent set. Detach was incomplete either way, since OnEnterParentTree establishes InheritanceParent but OnExitParentTree never cleared it - so a removed definition kept reading the grid's inherited PrivateSharedSizeScope, and the grid kept it alive as an inheritance child. Route every owner change through one transition that exits the old tree, assigns Parent, and enters the new one, and clear InheritanceParent on exit so detach mirrors attach. --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
…valoniaUI#21864) * fix(focus): infinite loop in tab stop search with TabNavigation=Once `FocusManager.FindNextElement(Next|Previous)` and `TryMoveFocus(Next|Previous)` never return when the focused element sits inside a container with `KeyboardNavigationMode.Once`. The calling thread spins at 100% CPU forever; in a desktop app that means a hard hang of the UI thread requiring the process to be killed. ## Root cause The upward walk in `GetNextTabStop` / `GetPreviousTabStop` advances at the end of each iteration with `parent = GetFocusParent(parent)`. But when the walk reaches a container whose `TabNavigation` is `Once` (or `None`, in one branch), the code resets `parent` from `focused` instead of from `current`: ```csharp current = parent; parent = FocusHelpers.GetFocusParent(focused); // focused is a loop invariant ``` `focused` never changes, so `parent` drops back down to the focused element's immediate parent. The next iteration walks up to the same container again and takes the same branch, so the walk oscillates between two nodes indefinitely. None of the three loop exit conditions (`parent != null`, `!parentIsRootVisual`, `newTabStop == null`) can ever be satisfied. The correct form already exists a few lines below in `GetNextTabStop`, in the structurally identical `KeyboardNavigationMode.None` branch: ```csharp current = pIE; parent = FocusHelpers.GetFocusParent(current); // walks up, converges ``` This changes the three remaining occurrences to match it: one in `GetNextTabStop`, two in `GetPreviousTabStop`. The two loop initializers outside the `while` (`FocusManager.cs:647` and `:748`) correctly keep using `focused` and are left alone. ## Reproducing it The focused element has to be nested **at least one level below** the `Once` container. When it is a direct child, `GetFocusParent(focused)` happens to return that same container and the walk terminates by accident - which is likely why this went unnoticed for so long. Minimal shape (used by both new tests): ``` StackPanel ├── StackPanel [TabNavigation=Once] │ └── StackPanel │ └── Button <- focused └── Button <- expected result for Next ``` Found in a production app: FluentAvalonia's `ContentDialog` calls `FindNextElement(NavigationDirection.Next, ...)` from its `Loaded` handler to pick an initial focus target. With focus sitting on a nested `NavigationView` item - the `Once` container comes from the NavigationView template - opening any dialog hung the app permanently. ## Scope Only the programmatic focus APIs go through this code. Pressing Tab is unaffected: `KeyboardNavigationHandler` uses the separate, WPF-derived implementation in `Navigation/TabNavigation.cs`, which handles `Once` correctly by passing the container itself as the new starting point. ## Verification - Two regression tests added to `InputElement_Focus`, covering both directions. - Confirmed they actually catch the bug: with the `FocusManager.cs` change reverted, the Next test ran for 90s using 89.5s of CPU and the Previous test for 60s using 59.6s before being killed. With the fix both return immediately. - Full `Avalonia.Base.UnitTests` suite: 2996 tests, 0 failed (2984 passed, 12 skipped). ## Not addressed here The `Once` branches are asymmetric: `GetPreviousTabStop` returns the container when it is focusable (`if (FocusHelpers.IsFocusable(parent)) newTabStop = parent;`), `GetNextTabStop` has no such check. Separately, in the Previous direction this shape ends up returning the focused element itself via the cycle fallback in `GetTabStopCandidateElement`, rather than the element preceding the container. Both look like genuine issues, but they are behavioural questions independent of the hang, so the Previous test only asserts that the call terminates. Happy to follow up in a separate PR if you would like them fixed. Co-Authored-By: Claude <noreply@anthropic.com> * fix(focus): previous tab stop search accepted candidates after the focused element Follow-up to the review feedback on the Previous test: asserting the exact element exposed that `GetPreviousTabStop` could not produce it. This turned out to be a second, independent porting error in the same code, so this commit fixes it and tightens both tests to exact-element assertions. ## Root cause `GetNextOrPreviousTabStopInternal` accepts an equal-tab-index candidate for the Previous direction with: ```csharp if (compareIndexResult < 0 || (((foundCurrent || currentPassed) || compareCurrentForPreviousElement) && compareIndexResult == 0)) ``` The WinUI implementation this code is ported from (see `CFocusManager::GetPreviousTabStopInternal`, faithfully mirrored in Uno's `FocusManager.mux.cs`) reads: ```cpp if (compareIndexResult < 0 || (((!bFoundCurrent && !bCurrentPassed) || bCurrentCompare) && compareIndexResult == 0)) ``` The negations were lost in porting, inverting the condition: since `TabIndex` defaults to `int.MaxValue`, sibling comparisons are almost always equal, so the Previous search skipped every element *before* the focused one and accepted elements *after* it. The Next direction's condition matches WinUI and is untouched. ## Impact Not limited to the `Once` scenario from the previous commit - `FindNextElement(Previous)` and `TryMoveFocus(Previous)` were wrong in a plain flat container: with focus on the third of four buttons, the search returned a following element rather than the preceding one, and where no following sibling existed it fell back to cycling, handing back the last focusable element in scope (observed in the Once test as "returns the focused element itself"). Keyboard Shift+Tab is unaffected as it uses the separate `TabNavigation.cs` implementation. ## Tests - `Can_Get_Previous_Element` (new): flat container, focus on target3, asserts target2 - locks both "skip candidates after the focused element" and "keep the closest preceding sibling" (not target1). - `Can_Get_Previous_Element_Out_Of_Container_With_TabNavigation_Once`: now asserts the exact element (`before`) instead of only termination, per review. - Verified both fail with the condition reverted and pass with it. - Full `Avalonia.Base.UnitTests`: 2997 tests, 0 failed (2985 passed, 12 skipped). ## Also spotted, not changed here The Previous/Cycle branch in `GetPreviousTabStop` calls `GetFirstFocusableElement` where WinUI calls `GetLastFocusableElement` (wrapping backwards inside a Cycle scope should land on the last element). Happy to fix that here too if you want it in this PR, otherwise I can open a separate one. Co-Authored-By: Claude <noreply@anthropic.com> * fix(focus): previous tab stop wrapped to the first element of a Cycle scope Third porting divergence found while comparing this code against the WinUI original (all three sit in the same two functions): the Previous/Cycle branch in `GetPreviousTabStop` called `GetFirstFocusableElement` where WinUI calls `GetLastFocusableElement`: ```cpp // WinUI, CFocusManager::GetPreviousTabStop if (IsValidTabStopSearchCandidate(pCurrent) && GetTabNavigation(pCurrent) == KeyboardNavigationMode::Cycle) { pNewTabStop = GetLastFocusableElement(pCurrent, pCurrent); break; } ``` Wrapping backwards inside a Cycle scope must land on the LAST focusable element, mirroring the forward wrap (last -> first). Taking the first element instead meant that with focus on the first tab stop of a `TabNavigation=Cycle` container, `FindNextElement(Previous)` returned the focused element itself and `TryMoveFocus(Previous)` was a no-op - focus could neither leave the scope (by design) nor wrap within it (the bug). Observed against the keyboard-path reference implementation on a Cycle container [a, b, c] with focus on `a`: `KeyboardNavigationHandler.GetNext(a, Previous)` returns `c`, this code returned `a`. The forward direction already wrapped correctly (`c` -> `a`) because the Next branch happens to use the correct element there. New test `Previous_Wraps_To_Last_Element_In_Cycle_Container` asserts the wrap target; verified it fails (returns the focused element) with the one-line change reverted. Full `Avalonia.Base.UnitTests`: 2998 tests, 0 failed (2986 passed, 12 skipped). Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…es visibility (AvaloniaUI#20798) * Add failing test for AvaloniaUI#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>
…UI#21867) * Allow single parameter with any type when binding to method * Port method binding logic to ReflectionBinding * Don't depend on the order of methods * Handle overrides properly * Fix nullability warning
* Add failing ScrollViewer tests * Handle Padding correctly in ScrollContentPresenter
* fix(macOS): commit IME preedit when switching focus between textboxes Fixes AvaloniaUI#19964 * remove comment --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
Member
Author
|
for fixes related with equality checks, check pixilonia-12 branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does the pull request do?
What is the current behavior?
What is the updated/expected behavior with this PR?
How was the solution implemented (if it's not obvious)?
Checklist
Breaking changes
Obsoletions / Deprecations
Fixed issues