* 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>
cd samples/IntegrationTestApp then ./bundle.sh to create an app bundle for IntegrationTestApp
Register the app bundle by running open -n ./bin/Debug/net8.0/osx-arm64/publish/IntegrationTestApp.app
Running
Run appium
Run the tests in this project
Each time you make a change to Avalonia or IntegrationTestApp, re-run the bundle.sh script (registration only needs to be done once).
Appium 2
Tests in this project are configured to run with Appium 1 (as only this version supports WinAppDriver).
If you need to run with Appium 2 on macOS, extra steps are required: