Pure Codename One editors and lightweight playground#5386
Conversation
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
|
Compared 12 screenshots: 12 matched. |
Blog prose gate✅ No net-new prose findings introduced by this PR. |
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
Cloudflare Preview
|
|
Compared 146 screenshots: 146 matched. Benchmark ResultsDetailed Performance Metrics
|
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 146 screenshots: 146 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 177 screenshots: 177 matched. |
|
Compared 146 screenshots: 146 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 147 screenshots: 147 matched. |
|
Compared 147 screenshots: 147 matched. |
5b12217 to
fdc26a7
Compare
|
Compared 150 screenshots: 150 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 148 screenshots: 148 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 149 screenshots: 149 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 217 screenshots: 217 matched. |
|
Compared 143 screenshots: 143 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 144 screenshots: 144 matched. |
… casts Three verified root causes of the "typing goes dead until you click another component and back" behavior in the lightweight editors: 1. Core session lifecycle: removing a focused EditorView (playground layout rebuilds, TextArea overlay teardown) clears form focus via setFocusedInternal WITHOUT firing focusLost, so the platform text-input session stayed bound and the stale handle blocked startInput on the next focus gain. EditorView now releases the session in deinitialize() and startInput rebinds over a leftover handle. Covered by the new EditorViewSessionTest. 2. JS port focus steal: the canvas mousedown default action blurs the hidden lightweight textarea (the worker-side preventDefault lands after the browser dispatch window) and the window key pipeline defers to the bound session, killing every key. The bridge now cancels the focus change synchronously while the lightweight input owns focus, and updateTextInputState re-asserts DOM focus so clicking back into the editor heals a lost binding. 3. ParparVM-JS array covariance: casting int[][] to Object[] (what List.toArray(new int[n][]) compiles to inside EditorView.bidiRuns) threw ClassCastException, breaking caret placement and typing on every line containing RTL text. The runtime checkcast/instanceof now resolve array covariance structurally. Also: IME composition now finalizes as a single undo unit against the pre-composition snapshot (undo previously corrupted offsets); composition updates invalidate layout; read-only editors no longer summon the keyboard and setEditable(false) ends an active session; RichView paints bidi lines in the same visual-atom order its geometry uses; CodeView tolerates null SyntaxHighlighter results; TextArea.setText reaches a live lightweight overlay; HtmlImporter preserves whitespace inside pre; the RTF serializer emits signed unicode values. Port consistency: stale-handle guards in Android/iOS stop/update SPI methods; Android maps constraint and action type into EditorInfo and delivers real editor actions plus hardware Ctrl shortcuts and a setComposingRegion bridge; iOS maps constraint/action to keyboard traits, routes single-line Return to the editor action, deletes whole composed character sequences, resets stale marked ranges across sessions, fixes a tvOS availability guard and a clipboard NSString leak; the JS port delivers Ctrl-modified navigation keys, no longer double-fires Enter actions, guards keydown/input against IME composition phases, and a stale drain no longer wipes the successor session's queued input. Playground/CI: restore CSS UIID completions through a CodeEditor completion provider; collapse the hidden messages strip with setHidden; editor screenshot tests drop the browser-era guards and capture on the editor ready event; the input verify harness now covers the caret-reposition click; scope the removed-editor tripwire to playground+core; extend the apt IPv4/retry hardening to all installs in the linux workflow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…test int[][] instanceof/checkcast Object[] and List.toArray(new int[n][]) are what EditorView.bidiRuns relies on; the fixture previously only exercised object array covariance so the runtime gap shipped unnoticed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…irror, rich-format undo iOS (verified on the iOS Simulator via a self-driven probe app: session start, programmatic edits, blur/refocus rebind, and interactively: tap-to-focus shows the caret, soft keyboard and selection accessory): - Every native-originated edit now carries a generation number that the Java side echoes back with each state push; the shadow drops stale echoes so a slow round trip can never regress the text or caret under fast typing. - setMarkedText/unmarkText forward through the client's composing contract (tiSetComposing/tiFinishComposing) like Android and JS, so IME composition reaches the editor's marked range, undo grouping and editing state. - insertText delivers as a commit (tiCommit) like the other ports, so typed-text hooks (auto indent, bracket pairing) and composition finalization behave identically across ports. - UIKit's synchronous text/selection queries answer from an immutable snapshot and layout geometry marshals onto the EDT; they previously read the EDT-owned document from the UIKit main thread mid-edit. Android (verified on the API 34 emulator: focus shows the keyboard, Gboard composition renders with candidates and the composing region round-trips through updateSelection; the pre-fix binary reproduced the IME desync where input goes dead after the first composed character): - The input connection keeps a synchronously updated mirror of in-flight edits so the IME's immediate surrounding-text re-reads (Gboard does this after every commit) see post-edit text; the mirror retires only once the EDT state push has caught up with every posted edit. Core: - Formatting commands (inline styles, block formats, links) now record undo units carrying rich-model snapshots: undo restores the pre-command styling without touching text, redo reapplies it, and undoing an earlier text edit no longer wipes formatting applied afterwards (RichViewFormatUndoTest). - Monospace (inline code) runs render with a subtle text-color tint so the semantic is visible; no monospace family ships with the framework fonts. - Removed the never-released deprecated backend-selection API (setDefaultBackend/getDefaultBackend/BACKEND_*) and regenerated the playground access registry without it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sion Hardware (Bluetooth / Chromebook) keys bypass the IME entirely, and the pure editor's raw key path is disabled while a platform session is bound, so physical typing was silently dropped. Route view-level key events through the same translation the IME-synthesized keys use (commands, editor action, unicode commit); unhandled keys (BACK, game keys) stay with the regular pipeline. Tapping an already-focused editor now re-requests the soft keyboard, matching EditText: a keyboard dismissed with the back gesture returns on the next tap instead of leaving the editor focused but keyboardless. Verified on the API 34 emulator: sustained Gboard composition (two consecutive composed keystrokes flow where the pre-mirror binary went deaf after one) with the composing region round-tripping through updateSelection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The header check compared the first line against "/*" without stripping the carriage return, so touching any historically CRLF source (parts of the Android port) failed the gate on a line-ending artifact rather than a copyright problem; the checker now normalizes CRLF before matching. Also add the standard header to the JsArrayCovarianceApp test fixture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The scoping comment added alongside the narrowed grep spelled out the forbidden editor name, so the tripwire matched the script itself and failed the playground smoke job. Reword the comment; the name stays split in the pattern for the same reason. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Bugs The editor screenshot tests captured on the backend ready event, which fires before the first paint flushes on the slower ports - Android and JS delivered frames without the editor content. Ready-event capture now chains into a FirstPaintGate that runs the capture only after the editor subtree actually painted: deterministic on every port, no fixed settle timers. The JS PureEditors golden still depicts the pre-covariance-fix render (blank lines after the first RTL line, from the int[][]-to-Object[] cast crash) and is adopted from CI artifacts in a follow-up once this run produces the correct frame. Also feed the keep-alive block's ti* query results into a consumed sink: the snapshot refactor made them provably side-effect-free, so their previously ignored returns started tripping the RV_RETURN_VALUE_IGNORED gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The FirstPaintGate addition put this previously header-less file in front of the copyright gate for the first time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A paint can run before layout assigned the editor its size (observed on the slower Android JDK matrix runners), and firing the capture there ships a frame without the content. The gate now requests another cycle from a pre-layout paint and fires on the first paint where the content has bounds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PixelCopy reads the window's last presented frame with no ordering guarantee against Codename One paints that were only just enqueued on the EDT; the async view renders them on a later UI-thread frame. The pure editor screenshot tests capture on the editor's ready event, which lost that race on the CI emulator and uploaded an empty content area while the same frame rendered correctly on screen. Invalidate the view and defer the PixelCopy by two vsyncs so the captured surface contains every paint enqueued before the capture request. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
setNativeFont handed every graphics context the Font object's own CodenameOneTextPaint, so all contexts drawing the same font aliased one Paint whose color each of them mutates. Async ops execute on the UI thread while the EDT paints mutable images, so a drawString on a mutable image could pick up another context's color mid-draw - observed on the CI emulator as the status-bar tap diagnostic composing its glass pane label in the wrong color. Each graphics context now keeps a private copy of the text paint, re-copied only when the font changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The file carries the original Android port's Pader-Sync GPL2 + Classpath-exception header, which its notice forbids altering; the checker only recognizes the Codename One and Oracle header forms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
api.github.com returns transient 5xx during incidents (observed: a 503 failing javase-simulator-tests twice and the website build once in one evening) and 429 under load. The release lookup in the simulator test runner now retries those with backoff like the download below it, and the OTA skin fetch passes --retry-all-errors so curl -f retries HTTP 5xx responses instead of failing on the first one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
During tonight's GitHub incident authenticated api.github.com requests returned 503 continuously while the same endpoint answered anonymous requests normally, so retrying with the token could never succeed. The token only exists to raise the rate limit; when the authenticated lookup exhausts its retries both skin resolutions now retry without it before giving up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copying the text paint in every graphics context washed out live text rendering across the whole screenshot suite - the async screen pipeline's enqueue-time caches rely on the shared paint identity. Only mutable-image contexts (the EDT side of the cross-thread color race) keep a private copy now; screen contexts alias the shared paint exactly as before. The editor screenshot tests additionally wait out any animation still in flight before capturing so a slow emulator cannot catch the form show transition mid-fade. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What changed
masterafter the revert in Revert "Pure Codename One rich text and code editors (remove BrowserComponent)" #5385.TextAreaandTextField.TextArea.setLightweightEditingEnabled(true)throughPlaygroundLightweightEditor.Why
PR #5378 was merged before the final CI result and then reverted. This replacement reapplies the final reviewed feature diff as one clean commit on the post-revert
master, while preserving the centered-dialog test registrations added afterward.The Playground now dogfoods the same lightweight editing API exposed to applications instead of maintaining a separate browser-based editor stack.
Validation
TextAreasource editorThis replaces #5378.