Skip to content

Wintab - #5

Open
flabbet wants to merge 512 commits into
PixiEditor:masterfrom
flabbet:wintab
Open

flabbet wants to merge 512 commits into
PixiEditor:masterfrom
flabbet:wintab

Conversation

@flabbet

@flabbet flabbet commented Dec 31, 2025

Copy link
Copy Markdown
Member

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

emmauss and others added 30 commits April 8, 2026 08:11
* 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
rabbitism and others added 29 commits July 29, 2026 15:10
* 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>
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>
@flabbet

flabbet commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

for fixes related with equality checks, check pixilonia-12 branch

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.