These notifications are only delivered to windows that opted in via
RegisterPointerDeviceNotifications, which we never call, so both
branches have been unreachable since they were introduced. They also
parse wParam as a pointer id, while these messages carry a device
handle there.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add failing test for template child presented inside Viewbox not being reparented on template change
When a ControlTemplate contains Viewbox > ContentPresenter presenting a
control that outlives the template, swapping the template throws
"The control already has a visual parent" because the old presenter
never releases the presented control.
Repro for #9551.
* Forward TemplatedParent to Viewbox's internal container so template teardown reaches its subtree
Viewbox hosts its Child inside an internal ViewboxContainer visual that
is a visual child but not a logical child of the Viewbox. Template
teardown (TemplatedControl.ApplyTemplate) finds descendants to
disconnect via GetTemplateDescendants, a visual-tree walk that stops
recursing at any visual whose TemplatedParent is null. ViewboxContainer
never had a TemplatedParent, so the walk stopped at it and template
descendants hosted inside the Viewbox (e.g. a ContentPresenter) never
had their TemplatedParent cleared. Their template bindings therefore
stayed live, the old ContentPresenter kept the presented control as its
visual child, and re-presenting that control in the new template threw
"The control already has a visual parent".
Forward the Viewbox's TemplatedParent to the container, restoring the
invariant that every template descendant is reachable through visuals
whose TemplatedParent is non-null. Null is deliberately not forwarded:
teardown clears the Viewbox's TemplatedParent while iterating lazily,
and forwarding null would prune the walk before it reaches the
container's subtree; the walk clears the container's TemplatedParent
itself instead.
Fixes#9551
* Trim down comment
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
TableViewColumn extends StyledElement. However, many features such as StyleSelectors did not work because no logical parent was set. This is solved by registering the TableView as a logical parent when the TableViewColumn is attached (and setting it to null when detacting).
* test(VirtualizingStackPanel): cover focused item virtualization
A focused item remains attached so keyboard focus can be preserved after it leaves the realized range. It must nevertheless stop rendering until it is realized again; otherwise an estimated position can surface it in the viewport.
* fix(VirtualizingStackPanel): hide cached focused items
A focused container stays attached after it leaves the realized range so keyboard focus survives. Its estimated position can overlap the viewport when item sizes vary, causing it to render and receive pointer input as a ghost item.\n\nSuppress rendering and hit testing while the container is cached, then restore its original state before re-realization or recycling. This preserves focus and template-provided opacity.
* fix(VirtualizingStackPanel): restore current focused container state
Focused-container suppression previously replayed the opacity and hit-test values observed when virtualization began. That could hide updates from bindings, styles, or application code while the container was retained.\n\nUse disposable animation-priority overrides for the temporary suppression so disposing them reveals the property's current underlying value.
* fix(VirtualizingStackPanel): keep retained focused container out of the viewport
The container of a focused item that leaves the realized range is retained
to preserve keyboard focus, and arranged at a position estimated from the
average realized element size. With differing item sizes that estimate can
place the container so that it overlaps the viewport, where it renders as a
ghost item and intercepts pointer input (#17935).
An unrealized item before the realized range always ends at or before the
range's start, and one after it always starts at or after the range's end.
Clamp the estimated arrange position to that invariant so the retained
container can never overlap the realized elements, replacing the previous
approach of masking the container with animation-priority opacity and
hit-test overrides.
* Proposal: Add week numbers to Calendar
* FluentTheme for adding CW
* Add sample to ControlCatalog about week numbers
* workaround for XAML not accepting empty strings
* SimpleTheme
* refractor TemplateParts of Calendar
* ensure Calendar updates and improve xml comment
* undo whitespace formatting
* Add some test to CalendarTests
* adress self review
* Introduce a method to show / hide the week numbers panel
since it is not part of the MonthGrid, it can leak into the year view. We solved this by updating IsVisible in code behind just like other template parts.
Moved the header into the panel to show / hide it together with the entire Grid.
* fix typo and redundant cast
* Crush the last moths
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* fix: correct HslColor.ToString() prefix from hsva to hsla
Pre-existing copy-paste bug: HslColor.ToString() was outputting
"hsva(" instead of "hsla(" for its default format.
* feat: implement unified IFormattable on Color, HslColor, and HsvColor
All three color types now support all format specifiers via
auto-conversion, following the DateTime analogy where the same
format codes work regardless of source type.
Format specifiers:
Hex: X (#AARRGGBB), x (#RRGGBB), H (#RRGGBBAA)
RGB: R/r (absolute), R%/r% (percent)
HSL: L/l (CSS standard), L%/l% (all percent)
HSV: V/v (CSS standard), V%/v% (all percent)
Convention: uppercase = include alpha (rgba/hsla/hsva prefix),
lowercase = exclude alpha (rgb/hsl/hsv prefix).
Each type handles its native model natively and delegates
cross-model formats via ToRgb()/ToHsl()/ToHsv().
Breaking changes from prior PR iteration:
- "h" dropped (identical to "x" without alpha)
- "C"/"c" removed, reserved for future complex format strings
- "P"/"p" replaced by "R%"/"r%"
- "R" now outputs rgba() not rgb() (CSS convention)
- "L" now outputs hsla() not hsl() (CSS convention)
- "V" now outputs hsva() not hsv() (CSS convention)
* refactor(media): clarify color CSS formatters
Color formatting now exposes the same IFormattable implementation in the BuildTask compile path as in normal builds. Keeping the interface conditional made the public contract harder to reason about even though the formatting members are System-only APIs.
Remove the BuildTask guard from the formatting members, combine alpha and no-alpha CSS helpers behind includeAlpha parameters, and rename the helpers so future changes preserve the CSS-compliant output contract.
* Remove regions
---------
Co-authored-by: Jumar Macato <16554748+jmacato@users.noreply.github.com>
Co-authored-by: Nathan Nguyen <HoangAnhVu.Nguyen-1@student.uts.edu.au>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* osx: anchor new windows to the primary screen origin
WindowBaseImpl::CreateNSWindow anchors the new NSWindow's content rect to the
primary screen's frame.origin. The primary screen is at Cocoa (0,0) on a
healthy Mac, but can be offset (often negative) while the display server is
mid-reconfiguration -- e.g. CGMainDisplayID() briefly returns 0 after
wake-from-sleep -- or on multi-monitor layouts where the primary is not at the
origin. Anchoring keeps the window on a real screen so it is positioned
on-screen and its flipped Position lands inside a Screen.Bounds.
See #18895.
Co-authored-by: Cursor <cursoragent@cursor.com>
* osx: keep window construction resilient when no screen contains it
When locating the screen that sizes a new window, fall back to a default size
if AppKit reports no screens -- or none whose bounds contain the last-known
position -- during a display reconfiguration. The window is repositioned on the
next ScreenChanged event once the display server settles.
See #18895.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Less verbose comments
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add VerticalContentAlignment property to DatePicker and TimePicker
This change registers VerticalContentAlignmentProperty as a
StyledProperty using ContentControl's property as the owner for both
DatePicker and TimePicker controls to maintain framework consistency.
Basic xUnit v3 unit tests are introduced to validate property
round-trips (Top, Center, Bottom, Stretch) and to ensure the default
value correctly resolves to Stretch. This establishes the necessary
C# infrastructure before modifying the control templates.
Part of #21211: implment fluent theme layout
* Fix VerticalContentAlignment bindings and integration tests
- Bind internal grids to VerticalContentAlignment in Fluent and Simple
themes for DatePicker and TimePicker controls.
- Add comprehensive integration tests using mocked NameScopes in
DatePickerTests and TimePickerTests to verify visual propagation.
- Validate visual layout correctness using the ControlCatalog app.
Closes AvaloniaUI#21211
* Remove tautological tests
---------
Co-authored-by: Martim Claudino <martimffclaudino@tecnico.ulisboa.pt>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add unit test for styling affecting measurements in WindowDrawnDecorationsContent
* Refactor layout measurement to apply styling before visibility checks
* Add core measure test
* Add StackPanel test
* Call ApplyStyling unconditionally in MeasureCore
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* fix(macOS): always raise keyDown before the input context sees the event
AvnView passed every keyDown to the NSTextInputContext first and only
raised a KeyDown when the context did not consume the event. The context
consumes every printable key by routing it to insertText:, so while a
text input client was active no KeyDown was raised for space, letters or
digits and a KeyGesture on those keys could never match. Only modified
keys were special-cased.
keyDown: now always raises exactly one KeyDown per NSEvent before the
input context is consulted. Composition state only decides which key is
reported: while hasMarkedText is set the key is masked as
AvnKeyImeProcessed, the same way Win32 reports VK_PROCESSKEY, so user
code still observes the event but no gesture matches it. The physical key
and the key symbol keep their real values in both cases.
If user code handles the event the input context is skipped entirely, so
no text and no preedit is produced. This mirrors the Win32 behaviour of
swallowing WM_CHAR after a handled WM_KEYDOWN.
The modifier special case, the handleKeyDown: helper and
_lastKeyDownEvent are gone. doCommandBySelector: is kept but empty, since
falling back to NSResponder would perform the default action and beep.
Adds a Keyboard page to IntegrationTestApp that reports the last key
down, a key down count and the last text input, plus Appium tests
covering gestures with and without a modifier, text suppression for a
handled gesture, and a single key down per key press.
* fix(macOS): mask the composition starting key for composing input methods
hasMarkedText only becomes true once a composition is in progress, so the
keystroke that starts one was still reported with its real key and could
match a KeyGesture. Win32 reports VK_PROCESSKEY for that keystroke too.
keyDown: now also masks the key as AvnKeyImeProcessed when a printable
character key is typed into a text input client while the selected
keyboard input source is a composing input method.
Whether an input source composes is resolved through
TISGetInputSourceProperty: anything that is not a plain keyboard layout
composes, except an input method in the alphanumeric input mode, which
passes keys straight through and therefore keeps the real key. Unknown
input sources keep the real key as well, so gestures are never lost to a
failed lookup. The lookup includes installed but not enabled input
sources, since an input method mode can be selected without being listed
as enabled, and the result is cached per input source id because this runs
for every key down.
Only printable character keys are masked. KeySymbolFromScanCode reports
the control character for Backspace, Enter, Tab and Escape, so the
presence of a key symbol is not enough to decide: masking those would stop
TextBox from reacting to them, which broke Backspace while an input method
was selected. Command and Control combinations are shortcuts and are not
masked either.
Plain keyboard layouts are unaffected: dead key compositions are not
driven by the input source and stay covered by hasMarkedText.
The Keyboard page now subscribes to KeyDown and TextInput with
handledEventsToo, so keys TextBox handles in its class handler, such as
Backspace and the arrows, stay visible in the readout.
* test(macOS): skip the Keyboard tests on the Appium 1 leg
The tests synthesize key input through W3C actions, which the mac2
driver bundled with Appium 1 does not implement, so on the macOS CI leg
they could only fail. They keep running on Windows, where WinAppDriver
handles W3C actions, and on macOS builds with IsRunningAppium2, which
target a current mac2 driver. The infrastructure change that would run
them on macOS CI is split out for a separate pull request.
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add new IPlatformSettings APIs
* Add control catalog PlatformSettingsPage
* Windows PreferredApplicationLanguage implementation
* Browser PreferredApplicationLanguage implementation
* Run API suppressions for the IPlatformSettings
* Rebase PlatformSettingsPage on new ContentPage
* Return CultureInfo.InstalledUICulture instead of CultureInfo.CurrentUICulture for default PreferredApplicationLanguage implementation
* Android PreferredApplicationLanguage implementation
* iOS PreferredApplicationLanguage implementation
* Use GetUserPreferredUILanguages for Win32 implementation instead of GetUserDefaultLocaleName
* MacOS implementation of PreferredApplicationLanguage
* Use GlobalizationPreferences for WIn32 prefered language, GetUserPreferredUILanguages doesn't work as expected with Windows settigns
* Avoid AvaloniaLocator in control catalog
* Remove unused method
* Add value/remarks XML docs on the PreferredApplicationLanguage
* feat: add support for CreateSourceInfo in design window loader
* Move XAML SourceInfo default to RuntimeXamlLoaderConfiguration
Applies to all designer/runtime load paths now; newer VS and VS Code designers do not use DesignWindowLoader.
---------
Co-authored-by: Kim Henrik <KimHenrik@outlook.de>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Correctly set ActualThemeVariant
* Don't call OnColorValuesChanged unnecessarily on Win32
* Don't call OnColorValuesChanged unnecessarily on macOS
* Change iOS PlatformSettings to match other platforms
* Don't call OnColorValuesChanged unnecessarily on Android
* Android: set theme using SetLocalNightMode
* Don't call OnColorValuesChanged unnecessarily on X11/Wayland
* Don't call OnColorValuesChanged unnecessarily on Browser
* Fix timer Start order
* Remove dead code in DBusPlatformSettings
* [Android] Fix TryGetFileFromPathAsync/TryGetFolderFromPathAsync returning null for content:// URI
* [Android] Add URI scheme constants in AndroidStorageProvider
* Implement visual geometry hit testing
* fix xml comment
* fix xml comment
* update api diff
* Introduced ICompositionHitTester to avoid duplicated hit test code between point and geometry
* Add geometry hit testing page to RenderDemo
* fix geometry hit testing not including stroke
* fix test
* update api and tests
* update api diff
* Update GeometryHitTestingPage with new API
* addressed reviews.
* remove nullability in GeometryHitTestResult Visual hit
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Add failing test for boxed booleans in compiled binding getters
Compiled-binding getters for bool properties emit 'box' on every read,
allocating a fresh object each time (#21065 reports ~300K allocations in
a real app). Add BooleanBoxes with two cached boxed values and a test
asserting that a compiled binding to a bool property produces the cached
box instances. BooleanBoxes must be public because compiled XAML IL is
emitted into user assemblies, which need to reference its fields.
* Reuse cached boxed booleans in compiled binding getters
Instead of emitting 'box bool' in the generated property-info getter,
emit a branch that returns BooleanBoxes.True or BooleanBoxes.False, so
reads of bool properties through compiled bindings no longer allocate.
Other value types keep the existing box. Applies to both the build-time
XAML compiler and the runtime XAML loader, which share this emitter.
Fixes#21065
* fix: emit cached boolean boxes into the generated per-assembly helper
The cached boxed booleans used by compiled-binding bool getters were
exposed as a new public BooleanBoxes class in Avalonia.Base, adding
public API surface that is useful only to compiled XAML. Review asked
for the boxes to stay an implementation detail instead.
Define two private static fields and a static constructor on the
XamlIlHelpers type the XAML compiler already generates into each user
assembly, and point the getter IL at those. The fields are shared by
all XAML files in the assembly, so allocation behaviour is unchanged
while no public API is added. The test now asserts box identity across
repeated reads instead of referencing the removed class.
On Android, composing/autocorrect text is written as live text while only a
composition region is tracked. IME edit operations (commitText,
finishComposingText) are queued and flushed on EndBatchEdit, but SendKeyEvent
dispatched the key immediately, bypassing the queue.
When a soft keyboard batched "commit autocorrect + press Enter", the newline was
inserted before the queued commit flushed. The commit then applied with stale
pre-newline composition indices and reset the caret to the end of the committed
word, leaving it on the previous line instead of the new one.
Route SendKeyEvent through the command queue via a new KeyEventCommand so key
events apply in FIFO order with the queued edit commands, honoring Android's
InputConnection batch-edit ordering contract. The autocorrect now commits first,
then the newline is inserted, leaving the caret on the new line. Outside a batch
edit the key is still dispatched immediately, preserving existing behavior;
hardware key input uses a separate path and is unaffected.
Fixes#21895
Co-authored-by: Emmanuel Hansen <emmausssss@gmail.com>
* [Automation] Fire property-changed events when AutomationId changes at runtime
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
* refactor: extract hardcoded dimensions to theme resources
Move hardcoded padding, margin, width, height, and border thickness values from individual control themes into centralized theme resources in BaseResources.xaml. This enables better theme customization and density style support while reducing duplication across control definitions.
* Rename Internal to Inner
---------
Co-authored-by: dimension-zero <info@ditech.ai>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* fix(SelectableTextBlock): fix SelectableTextBlock selection for centered and right-aligned text
* Fix failing unit tests
* Let TextLayout handle out-of-bounds hit testing
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* fix(input): fix AccessKeyHandler when no descendant control has focus
- Update IsFocusWithinOwner to use routed event's Source instead of re-querying KeyboardDevice.Instance.FocusedElement
- Allow access keys (Alt/mnemonics) to work immediately after Window opens when FocusedElement is null or owner itself
- Update shared test helpers in AccessKeyHandlerTests to populate event Source
Fixes#21806
* fix(input): address review feedback on AccessKeyHandler focus fix
- Type IsFocusWithinOwner's owner parameter as InputElement (matching
_owner) and drop the now-redundant `is Visual` check
- Fix indentation in IsFocusWithinOwner
- Add Should_Raise_AccessKey_When_Focus_Is_On_Descendant, covering the
IsVisualAncestorOf branch by raising KeyDown/KeyUp on a descendant
control instead of the owner
- Revert the no-op Source assignment in the KeyDown/KeyUp test helpers
- Shorten the comment in Should_Raise_Key_Events_For_Registered_Access_Key
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
The native `NSSavePanel` does not let you pick file packges like
`Application.app`-bundles by default.
Since the file picker does not return these bundles either,
picking these bundles is currently impossible.
By enabling `treatsFilePackagesAsDirectories` users can select
a bundle and pick it as a folder, and also select the contents of that
package.
* Add non-overlay popup support to the headless platform
When AvaloniaHeadlessPlatformOptions.UsePlatformPopups is enabled,
popups are hosted in dedicated headless top-levels positioned via
ManagedPopupPositioner instead of the parent's overlay layer.
HeadlessWindowExtensions.GetOpenPopups exposes the popups open above
a given toplevel. PointToScreen/PointToClient now account for the
window position, so popup placement can be asserted in desktop
coordinates.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Rename UsePlatformPopups to OverlayPopups for consistency with other platforms
Inverted semantics to match Win32/X11/macOS options; defaults to true
for now so existing headless test suites keep overlay popup behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Expand security policy with response expectations, supported versions and scope
Part of the coordinated vulnerability disclosure rollout: document
response-time commitments (acknowledge in 2 business days, timeline in
10), state the supported-versions policy (12.x), and clarify which
packages this policy covers.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mike James <mike@avaloniaui.net>
SetSubMenu left the item's own didSelectItem: action in place, so AppKit dispatched the click to it and dismissed the menu. Install submenuAction: as -[NSMenu setSubmenu:forItem:] does, and restore didSelectItem: when the submenu is removed, since the same NSMenuItem is reused.
Fixes#21886
attributedSubstringForProposedRange:actualRange: read *actualRange on
entry and used it as the proposed range. actualRange is an out parameter
and is uninitialized on entry, so the substring was taken from an
arbitrary range. It also never wrote the out parameter. It now intersects
the requested range with the document and writes the result, or
{NSNotFound, 0} when the intersection is empty.
The same class of issue affected the rest of the protocol implementation:
- firstRectForCharacterRange:actualRange: never wrote actualRange, and
dereferenced the parent without a null check.
- unmarkText dereferenced the parent without a null check.
- selectedRange and setSelection:: passed the managed selection through
unclamped, so a stale or reversed selection produced a range past the
end of the document, which AppKit then fed back into the substring
call. Reversed pairs are now swapped and both ends clamped.
- markedRange returned {selectionLocation, 0} instead of the documented
{NSNotFound, 0} when there is no marked text.
- The replacement ranges in setMarkedText:selectedRange:replacementRange:
and insertText:replacementRange: are clamped before being passed to
SelectInSurroundingText.
- setText: re-clamps the stored ranges, as replacing the document can
strand them out of bounds.
Nil strings and nil UTF8String results are no longer passed across the
COM boundary, and SetSurroundingText no longer calls
stringWithUTF8String: on a null pointer.
* Expose IRef/IImageBrushSource, update build/api suppressions
* Hide IRef from image brush source API
Internalized `IRef<T>` and removed it from the `IImageBrushSource` public surface by making `Bitmap` internal. Added a `[PrivateApi]` `GetBitmap()` helper returning `IBitmapImpl?` so internal consumers can still access the bitmap without exposing ref-count internals. Updated Skia drawing code to use `GetBitmap()` and refreshed API suppression entries accordingly.