Skip to content

Conversation

@MartinZikmund
Copy link
Member

@MartinZikmund MartinZikmund commented Jan 8, 2026

GitHub Issue: closes #22230

PR Type:

What is the current behavior? πŸ€”

What is the new behavior? πŸš€

PR Checklist βœ…

Please check if your PR fulfills the following requirements:

Other information ℹ️

Copilot AI review requested due to automatic review settings January 8, 2026 18:58
@github-actions github-actions bot added platform/wasm 🌐 Categorizes an issue or PR as relevant to the WebAssembly platform area/automation Categorizes an issue or PR as relevant to project automation labels Jan 8, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes backspace support on Android browser soft keyboards for WebAssembly Skia TextBox implementation. The issue is that Android soft keyboards return keyCode 229 (IME processing) for all keys, making it impossible to detect backspace via keydown events. The fix uses the beforeinput event to detect delete operations via their inputType, and allows the browser to handle deletions natively.

Key Changes:

  • Uses beforeinput event to detect delete operations on Android soft keyboards
  • Adds flag-based mechanism to skip preventDefault() for delete operations
  • Includes fallback check for ev.key on desktop browsers where beforeinput timing differs
  • Adds manual test sample for validation

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
BrowserInvisibleTextBoxViewExtension.ts Core fix - adds beforeinput listener to detect delete operations and skip preventDefault to allow native browser handling
TextBox_Backspace_SoftKeyboard.xaml.cs Code-behind for manual test sample with TextChanged handlers and character count display
TextBox_Backspace_SoftKeyboard.xaml Manual test UI with multiple TextBox/PasswordBox scenarios for testing the fix

Comment on lines +56 to +68
<Border Background="#FFF3E0" CornerRadius="8" Padding="15" Margin="0,20,0,0">
<StackPanel Spacing="8">
<TextBlock Text="Test Instructions:" FontWeight="Bold" />
<TextBlock TextWrapping="Wrap" Text="1. Tap each text field to open the soft keyboard" />
<TextBlock TextWrapping="Wrap" Text="2. Use the backspace key to delete characters" />
<TextBlock TextWrapping="Wrap" Text="3. Verify the text updates correctly after each backspace" />
<TextBlock TextWrapping="Wrap" Text="4. Test with different Android keyboards (GBoard, Samsung, SwiftKey)" />
<TextBlock TextWrapping="Wrap" Text="5. Test with autocomplete enabled and disabled" />
</StackPanel>
</Border>

<!-- Character count display -->
<Border Background="#E3F2FD" CornerRadius="8" Padding="15" Margin="0,10,0,0">
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XAML uses hard-coded colors for the instruction and character count borders (Background="#FFF3E0" and Background="#E3F2FD"). According to the XAML sample guidelines, UI elements should use ThemeResource for backgrounds and foregrounds to ensure proper theme adaptation between light and dark modes. Consider using theme-aware resources instead of explicit color values.

Copilot uses AI. Check for mistakes.

private void MultilineTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var lineCount = MultilineTextBox.Text.Split('\r').Length;
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line counting logic splits on '\r', but this may not work correctly across all platforms. Line endings can be '\n' (Unix/Linux), '\r\n' (Windows), or '\r' (old Mac). Consider using a more robust approach like Text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).Length or using TextBox's built-in line counting capabilities if available.

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,4 @@
ο»Ώnamespace Uno.UI.Runtime.Skia {
namespace Uno.UI.Runtime.Skia {
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description is missing the required GitHub issue link. According to the repository guidelines, every PR must reference a proper GitHub issue using the format:

  • Fixes https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER> or
  • Closes https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER> or
  • Related to https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER>

The PR description currently shows "closes #" without an issue number. Please provide the issue number this PR addresses, as mentioned in the code comments (issue #22230).

Copilot generated this review using guidance from organization custom instructions.
// Check if beforeinput indicated this is a delete operation.
// If so, let the browser handle it natively (don't preventDefault).
if (BrowserInvisibleTextBoxViewExtension.skipPreventDefaultForDelete) {
BrowserInvisibleTextBoxViewExtension.skipPreventDefaultForDelete = false;
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flag skipPreventDefaultForDelete is reset to false after being checked, but there's a potential race condition or timing issue. If multiple keydown events occur in quick succession before a single beforeinput event, the flag could be cleared prematurely. Consider using a more robust mechanism, such as storing an event timestamp or ID to pair beforeinput events with their corresponding keydown events.

Suggested change
BrowserInvisibleTextBoxViewExtension.skipPreventDefaultForDelete = false;

Copilot uses AI. Check for mistakes.
Comment on lines +135 to +140
// Also check ev.key for desktop browsers where beforeinput may fire after keydown
// or for cases where beforeinput isn't supported.
if (ev.key === 'Backspace' || ev.key === 'Delete') {
ev.stopPropagation();
return;
}
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic has a potential issue: the code checks for Backspace/Delete keys at lines 137-140 and returns without calling preventDefault(), but this means these keys will NOT be prevented from their default behavior even on desktop browsers where the original preventDefault() approach may have worked correctly. This could change existing behavior for desktop platforms. Consider checking if this is running on Android or if beforeinput is supported before skipping preventDefault(), to avoid affecting other platforms.

Copilot uses AI. Check for mistakes.
@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22316/docs/index.html

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22316/wasm-skia-net9/index.html

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

Labels

area/automation Categorizes an issue or PR as relevant to project automation platform/wasm 🌐 Categorizes an issue or PR as relevant to the WebAssembly platform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WASM Skia] Backspace key does not work (TextBox, PasswordBox)

4 participants