* Use 0 degree rotation angle in DrawRoundedCornersRectangle() for Rect
* Fix units in rotationAngle comment
* Improve ArcTo() XML docs
* Remove unused PiOver2 const causing build checks to fail
---------
Co-authored-by: Steven Kirk <grokys@users.noreply.github.com>
* Add AttachedPropertyAttribute, DirectPropertyAttribute and StyledPropertyAttribute attribtues
* Add shared GeneratedPropertyShape
* Move AvaloniaPropertyAnalyzer ids to DiagnosticIds
* Add generated properties analyzer descriptors
* Implement GeneratedPropertyAnalyzer
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Implement GeneratedProperty code fixers
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Update solution files with new projects
* Enable new diagnostics on Avalonia code itself
* Fix VB project
* Implement actual PropertyGenEmitter
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Replace several manual property declarations in ControlCatalog with new source gen
* Implement basic ConvertToGeneratedProperty analyzer, without code-fixer
* Lower supported C# version to 13
* Misc
* Add AvaloniaPropertyGeneratorIsEnabled msbuild prop
* Fix SetCurrentValue warning
* Use RegisterSyntaxNodeAction instead of RegisterOperationAction for new analyzer
* Fix some of the new CodeFix tests
* Support AddOwner to other generated properties
* Remove `AllowMultiple = false`, it's implied by default
* Remove ChangedMethodName
* Rename new attributes with "Generated" prefix
* Misc improvements
* Enable nullable per each property
* Switch to #nullable enable annotations to not break warnings
* Do not enforce partial callbacks, instead use existing warning if method is missing or incorrect
* Support callbacks defined in the base class
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Jumar Macato <16554748+jmacato@users.noreply.github.com>
* ControlCatalog: add dashboard home page with animated hero and nav cards
A new Home page (first in the drawer) modeled on the Accelerate demo
dashboard: a gradient hero banner with floating control glyphs animated
via keyframed TranslateTransforms, followed by categorized card sections
for every catalog page. Cards carry an icon badge, title and one-line
description, and clicking one navigates via SelectedPageIndex so the
drawer selection stays in sync. PageItem gains Description/Category and
the view model exposes grouped HomeSections plus NavigateToPageCommand.
Card colors are self-contained theme dictionaries so the page works
across Fluent/Fluent2/Simple in both variants.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ControlCatalog: use the Accelerate demo hero banner verbatim on the home page
Replaces the gradient/glyph hero with a 1:1 copy of AvaloniaProDemo's
DashboardView banner: banner-bg backdrop, the four 3D logos floating at
the original positions/durations, and the centered Avalonia wordmark.
Assets copied from the Accelerate repo (~4.8 MB of PNGs).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* DataGridPage was removed
* Make Main Window a bit wider to fit 3 full columns instead of 2.5
* Fix ScreenPage not rendering
* Replace Avalonia old icon with a new one
* Update main logo too
* Force Avalonia SyncContext inside of OnSizeChanged callback
* Restructure MainWindowViewModel_PageList, avoid duplication of categories
* Fix screens page invalidation
* Fix minor warnings
* Redo HomePage items layouting
* Add missing pages
* Reuse $(SharedAssetsPath)
* Don't pin exact patch version of DiagnosticsSupport
* Resize new assets
* Include page section in search
* Use expression setters in main view model
* Restore filtered page sorting
* Fix CI build
* Add 1px margin to the UniformGrid to fix cropped border issue
---------
Co-authored-by: Mike James <michael.james6@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add failing test for a right-to-left split inside a cluster
Splitting a right-to-left shaped buffer keeps a straddling cluster's
glyphs together in the leading half, but cuts the text at the requested
offset instead of following them. The halves then disagree about which
characters their glyphs cover: the leading half claims one character
while holding the glyphs for two, and the trailing half claims a
character whose glyphs it doesn't have. The left-to-right path already
snaps the text boundary to the cluster.
* Snap a right-to-left split to the cluster the glyphs stay with
A cluster straddling the split point keeps all its glyphs in the leading
half, so the text has to be cut where those glyphs end, not at the
requested offset. Cutting at the offset produced two halves whose glyph
and character coverage disagreed, and their shared cluster cache then
described neither: measuring the trailing half returned counts that cut
a cluster, and splitting it again could hand back a leading half holding
every glyph and no trailing half at all - a null run that crashed the
bidi reorderer.
The ascending path already snapped this way; this makes the descending
path match.
* Add failing tests for SelectionBoxItem with a control
* Use ItemTemplate for ComboBox's selection box for controls
* Add failing selection box tests when properties change
* Update selection box when its template changes
* Add failing test: CompositionDrawingSurface update processed after Dispose orphans the GPU snapshot
A commit batch is processed on the render thread in serialization order: the
dispose list is written before queued server jobs. The legal user-code order
`surface.UpdateAsync(image); surface.Dispose();` therefore executes on the
render thread as Dispose() -> UpdateWithAutomaticSync(), and the update stores
a fresh snapshot ref into the already-disposed ServerCompositionDrawingSurface.
Nothing disposes that ref afterwards, so the GPU-backed snapshot is cleaned up
by the RefCountable.Ref<T> critical finalizer, which performs GPU work on the
finalizer thread and races the compositor render loop (#21865).
* Fix ServerCompositionDrawingSurface orphaning GPU snapshots when an update is processed after Dispose
Add a disposed flag: an Update processed after Dispose now disposes the fresh
snapshot immediately on the render thread (where the GPU context is current)
instead of storing it into the disposed surface where nothing will ever
release it. This removes the finalizer-thread GPU cleanup path that races the
compositor render loop and crashes in sk_canvas_flush (#21865).
* Add failing test for a word gap at a run boundary
Justification collects break opportunities run by run. The line breaker
always reports a break at the end of the text it is given, and that
artificial run-final break is filtered out - so a real word gap that
happens to fall on a run boundary produces no opportunity at all and is
never widened. A line whose word gap borders a fallback run is left
partly or entirely unjustified.
* Search break opportunities in the line text, not per run
A run boundary is not a text boundary - a font fallback or a style
change splits a run mid-sentence - but the line breaker reports a break
at the end of whatever text it is given. Searching run by run invented a
break at every run boundary, and dropping those artefacts also dropped
every real word gap that fell on one.
- collect the opportunities from each stretch of consecutive text runs,
copied into a pooled buffer, and exclude only the stretch-final break
- runs that carry no text (embedded objects, end of line) end a stretch,
as do runs whose length doesn't match their text, since neither can be
mapped back to text source positions by offset
* Add Emoji, Emoji_Presentation and Default_Ignorable Unicode data
Font fallback has to tell content codepoints apart from ones a font is not
expected to draw, and emoji presentation cannot be decided from the general
category alone. None of that data was available.
- Pack Emoji, Emoji_Presentation and Default_Ignorable_Code_Point as single
bits into the spare bits of the GraphemeBreak trie word (it only used 7 of
32); the emoji properties come from the emoji-data.txt the generator already
reads for Extended_Pictographic.
- Expose them as Codepoint.IsEmoji, HasEmojiPresentation and IsDefaultIgnorable.
- Regenerate GraphemeBreak.trie.cs; no other generated file changes.
* Add failing test for default ignorables in cluster coverage
A cluster of base + U+FE0F + combining mark is handed to the primary font even
though it has no glyph for the mark, because every candidate font is required
to cover the variation selector as well and none does. The mark renders as
.notdef.
The fallback font is Noto Sans rather than DejaVu Sans: DejaVu maps U+FE0F and
would hide the defect.
* Ignore default ignorable codepoints when matching cluster coverage
Variation selectors are nonspacing marks by general category, so the cluster
coverage check demanded a glyph for them from every candidate font. Text fonts
do not map U+FE0F, which made any base + U+FE0F + mark cluster look unmatchable:
the fallback search was keyed on the variation selector, found nothing, and the
cluster fell back to the primary font with the mark rendered as .notdef. This is
what made emoji keycap sequences render as a digit followed by a tofu box.
- Skip default ignorables (along with the break/control/format codepoints
already handled) when testing cluster coverage and when picking the codepoint
the fallback search is keyed on.
- A cluster holding only a default ignorable no longer ends a shapeable run;
it renders nothing whichever font it lands on.
* Unify glyph-demand predicate in cluster coverage
Default_Ignorable_Code_Point already covers every invisible format
codepoint, so the blanket Format exclusion in NeedsGlyph only skipped
the deliberately visible ones (prepended concatenation marks like
U+0600, interlinear annotation chars) - those should demand a glyph,
and the base-only pass already did. Dropping Format makes NeedsGlyph
identical to the run-ending condition in TryGetShapeableLength, which
now calls it instead of restating it.
* invalidate image measure when IAffectsRender source invalidates
* compare drawing image bounds when checking for measure invalidation
* addressed nit
* use dispatcher run overload in test
* gate subscription behind attachment
* fix typo
* add one more attached check
* nit if style
* Fix pointer capture cancellation on Win32
A cancelled pen or mouse interaction was reported as an ordinary leave,
and nothing released the capture that came with it, so the captured
element never saw PointerCaptureLost.
Win32 constants: POINTER_FLAG_CONFIDENCE and POINTER_FLAG_CANCELED were
declared an order of magnitude too small - the SDK defines them as
0x4000 and 0x8000 - so the cancellation check in GetEventType could
never match. Ctrl+Alt+Del or Win+L mid stroke therefore arrived as a
normal button up, and the app committed an interaction the user had
aborted.
Win32 handling: WM_POINTERCAPTURECHANGED and POINTER_FLAG_CANCELED now
map to CancelCapture for non touch pointers, matching what the legacy
WM_CAPTURECHANGED path has always done.
PenDevice: handle CancelCapture by releasing the capture while keeping
the pointer alive, since the pen is still in range and a leave arrives
separately.
Pointer hardening: CaptureLost ends every capture the pointer holds, on
the element and on a gesture recognizer, and the devices release through
it instead of repeating the steps. Capturing to a recognizer clears
Captured, so the null check in the platform path used to skip the whole
release while a scroll, pull or swipe gesture owned the pointer, and a
touch up never cleared the recognizer at all. Dispose releases as well
rather than leaving that to every caller, a disposed pointer ignores
further capture calls and asserts when a capturer is passed, and devices
drop a pointer from their map before disposing it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Keep the explicit capture source in MouseTestHelper
The helper captures through Pointer.Capture(target), which is an
explicit capture, and used to release with Capture(null) - explicit as
well. Releasing as implicit changed the source that capture changing
handlers observe.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Fix Win32 system menu for extended client area title bars
* Fix Win32 system menu behavior in extended client area and fullscreen
* Improve system menu display and default item behavior
* Clean up
* Fix SetMenuDefaultItem P/Invoke signature
* Fix system menu handling for Space key
* Allow controls to handle non-client right-click events
* Add failing test for stencil buffer default, single-source the policy
Stencil buffer selection was duplicated as `useStencilBuffers == false` across the
GL, Metal and Vulkan backends, so there was no single place to review or test the
default. Move it to SkiaOptions.ShouldAvoidStencilBuffers and add a test asserting
the contract the default should honour. The test fails at this commit.
* Avoid stencil buffers unless explicitly enabled
Enabling stencil buffers lets Skia select multisample-based path rendering, which
quantizes edge coverage instead of computing analytic coverage. Vector geometry
therefore rasterizes with visibly softer, rougher edges on GPU backends, most
noticeably on small icons. Text is unaffected because glyphs are drawn from the
mask atlas rather than the path renderer.
Make the null default avoid stencil buffers again, restoring 12.0.5 rendering.
Applications that want the faster clipping can still opt in explicitly with
SkiaOptions.UseStencilBuffers = true.
Fixes#21760
* Fix DatePicker and TimePicker separator alignment with VerticalContentAlignment
* Fix DatePicker and TimePicker separator alignment in Simple Theme
---------
Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
TopLevel teardown (HandleClosed) was only ever triggered by the backend
invoking ITopLevelImpl.Closed. Browser, iOS, Android, macOS and the offscreen
(designer previewer) impls never raise it from Dispose(), so
EmbeddableControlRoot.Closed was never raised there and StopRendering() was
never reached - the top level stayed registered in MediaContext forever.
Make teardown idempotent behind EnsureClosed() and call it from the managed
Dispose() paths (EmbeddableControlRoot, OffscreenTopLevel, PopupRoot). The
guard lives in a new non-virtual entry point because WindowBase and Window
override HandleClosed and run side effects before calling base.
Also drop ChoreographerTimer's view-visibility gate on Android. It predates
the render timer rewrite and vetoed ticks that DefaultRenderLoop had explicitly
asked for, so the synchronous compositor round-trip in HandleClosed
(Renderer.Dispose -> MediaContext.SyncDisposeCompositionTarget) could never
complete once the view had unsubscribed - deadlocking every activity destroy.
DefaultRenderLoop already owns the sleep/wake state machine, driven by
StartRendering/StopRendering, which makes the extra gate redundant.
Verified at runtime on X11, Wayland, Win32, macOS, Headless, Browser (WASM),
Android and iOS: Closed fires exactly once per teardown, MediaContext returns
to baseline, and platform-initiated closes still fire exactly once.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
AvaloniaAccessHelper keeps every automation peer it has ever handed to
Android in three dictionaries (_peers, _peerIds, _peerNodeInfoProviders)
and never removes any of them - the file contains no Remove or Clear call.
Each ControlAutomationPeer holds a strong reference to its Owner, so once
accessibility has explored a control, that control (and the visual tree
hanging off it) is pinned for the lifetime of the AvaloniaView.
This is invisible in an app with a static UI, but it is unbounded in one
that rebuilds its visual tree: on a digital-signage device rebuilding its
screen every 20-40 s, this retained one full dead screen per rebuild -
about 2.5 MB of live managed heap each time, measured after a forced
gen2 collection, growing until the low-memory killer stepped in.
Removing the stale entries brought the same bench from unbounded growth
to a flat plateau over 28 consecutive rebuilds.
The registration is now dropped when the peer's control is detached from
the visual tree, and the two peer event handlers are unsubscribed at the
same time (they were never removed either).
Virtual view IDs are now allocated from a monotonic counter instead of
being derived from _peerNodeInfoProviders.Count. That was safe only while
nothing was ever removed: with removal, Count can fall back onto an ID
that is still in use and the next registration would throw from
Dictionary.Add inside an accessibility callback.
The root peer (ID 0) is deliberately left registered: GetVirtualViewAt and
GetVisibleVirtualViews index _peers[0] directly, so removing it would
throw. It is a single entry, owned by the view, and dies with the helper.
* Fix TextBlock ellipsis not showing with TextWrapping and MaxLines
When TextWrapping and MaxLines are set, the collapsing width was using the
layout's maximum width instead of the current line's width. This caused the
ellipsis to not appear when the last line was shorter than other lines.
Also added HasCollapsed check to prevent double-collapsing when text has
already been collapsed due to overflow.
* Remove HasCollapsed check
* Add unit test for MaxLines trailing ellipsis on short wrapped lines
* Remove redundant comment
* fix: simplify TextLayout test
OnlyIfVisible paused properties applied directly to a Visual, but transform setters continued advancing because their AnimationInstance targeted a child Transform. This left scale and opacity out of phase after visibility was restored.\n\nCarry the owning visual separately from the property target so transform instances observe the same visibility and detachment lifecycle. Cover the pause and resume timeline with a regression test.
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
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