-
Notifications
You must be signed in to change notification settings - Fork 839
fix: Android browser WASM Backspace support #22316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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
beforeinputevent to detect delete operations on Android soft keyboards - Adds flag-based mechanism to skip
preventDefault()for delete operations - Includes fallback check for
ev.keyon 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 |
| <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"> |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
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.
|
|
||
| private void MultilineTextBox_TextChanged(object sender, TextChangedEventArgs e) | ||
| { | ||
| var lineCount = MultilineTextBox.Text.Split('\r').Length; |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
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.
| @@ -1,4 +1,4 @@ | |||
| ο»Ώnamespace Uno.UI.Runtime.Skia { | |||
| namespace Uno.UI.Runtime.Skia { | |||
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
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>orCloses https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER>orRelated 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).
| // 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; |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
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.
| BrowserInvisibleTextBoxViewExtension.skipPreventDefaultForDelete = false; |
| // 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; | ||
| } |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
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.
|
π€ Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22316/docs/index.html |
|
π€ 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 |
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:
Screenshots Compare Test Runresults.Other information βΉοΈ