VoiceWave grows an opt-in ptt_use_escape flag (Escape doubles as cancel/
dismiss elsewhere, so hosts choose); both keys drive the same logical talk
button. Gamemaker opts in via the caption_bar's hidden voice_wave and the
hints now read 'hold Esc' — the big friendly key for kids. Verified the
nested named-child merge lands on the live widget.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verdict on the gamemaker judder (measured, 25s A/B runs, same window size):
gauss OFF -> unchanged (25-33ms gaps) [pyramid exonerated]
empty game world -> unchanged [game exonerated]
vsync OFF -> FIXED (119.8fps steady, worst 9ms; slow callbacks 124->2)
The stall is CAMetalLayer display-sync throttling: the compositor (hardware-
mirrored + SwitchResX-scaled 7680x2160) returns drawables unevenly, and
nextDrawable blocks the main thread 10-25ms in phases. The durable fix is
present-gated pacing: track in-flight presents via addPresentedHandler and
skip the paint when the pool is busy instead of blocking the event loop.
MAKEPAD_TIMER_TRACE=1 logs paint-clock fire-to-fire gaps >20ms and slow
callbacks >10ms with a per-step breakdown (live_edit/net/pad/paint/gc).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixed 8ms timer0 presented ~125Hz into a 120Hz vsync queue: the drawable
pool drifted full and nextDrawable blocked the main thread in a ~25-frame
sawtooth (PerfGraph 'wait' ramps). Timer now arms at 1.002/max_fps across
attached NSScreens — the +0.2% makes NSTimer lateness drain the queue instead
of accumulating. Sawtooth verified gone.
perf_monitor: 'gpu' channel — presented-frame GPU interval tapped from the
existing command-buffer completion aggregation (atomic hand-off, folded at
frame_boundary; concurrent with CPU channels, plotted violet).
metal: MAKEPAD_GPU_PASS_TRACE=1 logs per-pass GPU time ([gpu-pass] name ms)
for frame-budget hunts.
Measured (gamemaker, empty world vs full racing game — identical ~4.7ms GPU):
the frame cost is the UI glass pipeline, not the game — scene capture +
6 mip downsamples + 3 smooth upsamples re-run every frame at 120Hz because
the game pane dirties the window; at low GPU clocks the 11-pass chain's
latency swings past the 8.3ms budget in phases.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
platform: Cx.perf_monitor — per-frame ring (240) of paint-to-paint gap +
per-channel CPU us. Built-in channels: event dispatch (outermost, minus
app-attributed time), script exec, GC, pass encode, nextDrawable wait.
Apps register custom channels: cx.perf_monitor.channel("physics", rgb).
Off until enabled; hooks in event dispatch, macos repaint, metal draw_pass.
widgets: PerfGraph — corner-pinned live panel (DrawVector strips): frame-gap
bars colored against 120/60Hz budgets with guide lines, stacked per-channel
CPU, legend with averages. Self-positions bottom-right (DrawVector geometry
+ deferred turtle alignment don't mix — no aligning parent).
gamemaker: PerfGraph hovers the game pane (F3 toggles), engine feeds script
+ physics channels (incl. hot-reload evals); engine text overlay moved to
F4; per-phase engine window kept for ag perf / AIGAME_PERF=1; new 'ag perf'
harness verb + template guidance (template CLAUDE.md force-added: runtime
resource, blanket CLAUDE.md gitignore had kept it untracked).
Measured on my-game-5: engine frame CPU ~0.3ms; the hiccup is frame pacing —
the 8ms NSTimer paint clock beats against the 120Hz display, the drawable
pool drifts full and nextDrawable blocks the main thread in a ~25-frame
sawtooth (avg 2-3.4ms, spikes 20-30ms). The graph shows it as red ramps.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* TextInput: expose the location of the caret/cursor
in absolute window-relative coordinates.
THis allows, for ex, a widget to be placed relative to the
current location of the text being inputted by the user.
* View: add fn for toggling `optimize` and force texture caching
Add CachedView fns that make it easier to control its parameters:
* set_optimize(cx, ViewOptimize): switch optimize mode at runtime and
allocate the draw_list on demand. Previously `optimize` was set once from
`texture_caching` and never reset, so a view couldn't toggle between direct
and texture-cached rendering per frame.
* set_texture_max_height(Option<f64>): cap the Texture-mode render turtle's
height so a tall Fit-height cached view can't allocate a render target past
the GPU's max texture size (was a hard MTLTextureDescriptor abort once
content exceeded 16384px). None (default) leaves it uncapped; content past
the cap is clipped. Only affects Texture mode.
* redraw_texture_cache() / force_texture_redraw: force one offscreen
re-render after a content repopulate or an optimize-mode flip. The
rect-based will_redraw check can't see a content change on a recycled or
toggled view, so without this it would composite a stale texture.
* view_size is now updated in every optimize mode, not just draw-list modes.
The None (direct-render) path previously left it stale, so a view toggled
None<->Texture sized its next offscreen turtle from an old height and
clipped/mis-positioned its content.
in absolute window-relative coordinates.
THis allows, for ex, a widget to be placed relative to the
current location of the text being inputted by the user.
- New GlassPanel widget (widgets/src/glass_panel.rs) + lib export
- gauss_view: honor surface_alpha for translucent glass surfaces
- examples/glass: standalone demo (wired into Cargo workspace + makepad.splash)
- rustfmt.toml: re-enable disable_all_formatting to stop rustfmt from
reformatting the whole tree on save
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Support standard keyboard navg shortcuts/keys in TextInput
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
* Add `CropToFill` image fit variant, improve ImageFit docs
This allows you to easily achieve the "centered cropped fit" that most apps
want for things like avatars or small thubmnails that get masked.
* Detect and support hardware keyboards, distinguish from soft/virtual kbd
Mimic desktop behavior on mobile systems as much as possible.
This is esp important for tablets like iPad OS where you're more likely
to have a real physical keyboard attached.
For iOS:
* Arrow keys and Home/End/PageUp/PageDown navigate and auto-repeat
at the system-defined rate (connected via `UIKeyCommand`)
* Cmd+Enter to submit a `TextInput` and Cmd+C/X/V clipboard shortcuts now work.
* Ensure the pop-up diacritic/accent menu is properly placed using a hidden
`UITextInput` native widget, which acts as a sort of "proxy"
* Proactively drain `ShowTextIME` after each draw so the IME position will be
properly updated after each keystroke.
* Importnatly, don't mark the IME dismissed when a hardware keyboard is attached.
For both iOS & Android:
* Add a `has_physical_keyboard()` detection mechanism across both backends,
and fix platform-specific key repeat behavior
For Android:
* Ensure clipboard cut/copy works using the same Ctrl shortcuts (API 26+)
Soft/virtual keyboard/IME changes:
* For multiline TExtInputs, a soft keyboard Enter/Return key will always just
insert a new line, to avoid complexity with keyboard shortcut cfgs.
* CJK keyboard character selection should also be properly positioned now
* minor optimization to avoid re-setting IME pos if it didn't change
* Ensure inline composition is still shown in TextInput on all platforms
This is mostly relevant when using CJK and other similar IMEs.
Previously Makepad didn't shown any "echoes" of the single latin chars
that the user would type, but it would correctly input the selected CJK
glyph. So if you typed `nihao` and then selected `你哈`, then you would
see the proper chinese characters but not the latin "nihao".
Tha't s a bit confusing while typing.
Summary of the fixes per platform:
macOS:
- `set_marked_text` now forwards the marked (composition) text to the
focused TextInput with `replace_last = true`; previously it only stored
it in an ivar. `unmark_text` clears the preview, and both it and
`insert_text` share a new `clear_marked_text_ivar` helper so a commit
doesn't emit a second, destructive text-input event.
Windows:
- Add `WM_IME_COMPOSITION` handling: commit `GCS_RESULTSTR`
(`replace_last = false`) and show `GCS_COMPSTR` inline
(`replace_last = true`), and clear on `WM_IME_ENDCOMPOSITION`. The
message is consumed so DefWindowProc neither draws its own composition
window nor synthesizes a duplicate WM_CHAR for the result.
- Extend the vendored `windows` binding with `ImmGetCompositionStringW`,
`GCS_COMPSTR`/`GCS_RESULTSTR`, and `WM_IME_COMPOSITION`/
`WM_IME_ENDCOMPOSITION`, which it didn't previously generate.
Linux (Wayland):
- Handle the `zwp_text_input_v3` `PreeditString` event (previously empty)
and apply the double-buffered preedit/commit state on `Done`, in the
protocol-mandated order (commit, then preedit), clearing the preview
when a cycle carries no preedit.
Linux (X11):
- Create the input context with XIM on-the-spot (`XIMPreeditCallbacks`)
and forward the preedit string from the draw/start/done callbacks,
falling back to `XIMPreeditNothing` if the IM server doesn't support
callbacks. Callbacks run inside `XFilterEvent`, so they only mutate a
thread-local that the event loop drains into the widget afterward,
avoiding re-entrant access to the app.
Android:
- Don't mark the IME dismissed when a physical keyboard is attached
(mirrors the iOS guard). Android was unconditionally calling
`text_ime_was_dismissed()` on soft-keyboard hide, which tore down the
IME connection that hardware-key composition relies on.
* iOS: replace custom `UITextInput` with a native `UITextView`
`UITextView` is a full system-native keyboard client, so we get all the
major features for free: language HUD pill and the complete globe/Ctrl+Space
shortcut to cycle between IMEs/languages.
Makepad basically just mirrors the state of the system native text view,
via the `full_state_sync`, but the actual native text view is kept invisible
so it doesn't interfere with what we render in Makepad's TextInput.
Notably, the Full Keyboard Accessibility setting now does work properly,
whereas it did not before with our UITextInput-based approach.
We also make sure that arrow keys, nav keys, auto-repeat, and modifiers
are properly hanlded so we can retain the expected kbd shortcuts,
like other desktop platforms.
* iOS: remove the old `UITextInput` connection with the Makepad TextInput
We've now switched to the native UITextview, so we don't need this any more.
* iOS: fix desync during fast typing
Ensure there's no race between the native UITextView and
Makepad's TextInput, as the Enter/REturn key needs special handling
w.r.t. how `pressesBegan` gets it (From a real hardware kbd).
* TextInput: more iOS integration, and text input types
more native integration for things like username/password,
new password fields, email, address, URLs, etc.
These tell iOS to change the keyboard layout/type for the text input.
* iOS: don't let Full Keyboard Access focus on our hidden native cursor
* cleanup
* iOS/TextInput: fix perf issues
* iOS TextInput: more fixes for read-only efficiency, and filtered input
Also port some of these fixes to Android's IME integration layer
* iOS/TextInput: hide the native caret iOS draws during autocorrect
but still allow the "decline autocorrect" bubble to popup where that
hidden caret is located (and the CJK candidate window in the same spot)
* Avoid script VM re-entrant panic: defer animator_cut/play if script VM is held
`animator_cut` / `animator_play` call `cx.with_vm`, which panics
(*"Script VM swapped off"*) when invoked during an apply walk — e.g. a
widget's `on_after_apply` on `ScriptReapply` / `Reload` — because the VM
is already taken for the duration of that walk's enclosing `cx.with_vm`.
- The derive macro's `animator_cut_scoped` / `animator_play_scoped` now
check `cx.is_script_vm_held()`; when held, they queue the op
(`defer_cut` / `defer_play`) and return instead of re-entering the VM.
- `animator_handle_event_scoped` replays the queue via `flush_deferred`
on the next frame, once the VM is free.
The defer path runs **only** in the formerly-panicking case, so VM-free
animations are byte-for-byte unchanged.
Also adds a re-entrancy-naming panic (`VmHolderGuard`) plus
`Cx::try_with_vm` / `Cx::is_script_vm_held` for diagnosing and handling
this class of bug.
* Better spacing/positioning for IME popups like the CJK candidate menu
applied to all platforms, but primarily an issue on macOS/iOS.
The candidate/conversion window (e.g. CJK pinyin) was covering the line of
text being composed. Carry the caret-line rect (not just a point) through
ShowTextIME and feed each backend its native "keep clear of this line" API,
so the OS places the candidate directly above/below the line with a small gap:
- macOS: firstRectForCharacterRange returns the line rect via AppKit
convertRect:toView:nil + convertRectToScreen (drops the hand-rolled
screen-coord math + fudge offsets); invalidate on caret move.
- Windows: ImmSetCandidateWindow with a CFS_EXCLUDE line rect.
- Wayland: set_cursor_rectangle with the real line rect.
- X11: XNSpotLocation/XNArea at the line.
- iOS: return the true composing-line box from firstRectForRange so iOS flips
around the real edges (consistent at any screen position) instead of a
degenerate point; only while marked text is active, to avoid an oversized
autocorrect highlight when typing normally.
* Fix Linux X11 behavior: Ctrl-based kbd shortcuts didn't work in TextInput
also trying to fix X11 behavior for positioning the CJK candidate window,
turns out there was an X11 bug for Ubuntu 22 and older so it's not always
possible, but we can attempt a workaround if errors occur (based on that,
we try to auto-detect the version of X11)
* fix X11 event loop latency by draining only a max of 64 events before redrawing
still working on X11 CJK candidate window positioning...
* add logs to X11 ime to figure out wtf is going on
* more robust fallbacks for X11 CJK candidate window positioning... grr
* maybe try to set the XFontSet attribute? for CJK candidate positioning
* positioning works now but there is a bit of overlap still
* now that X11 CJK candidate positioning works in some cases,
we need to pass the full rectangle containing the current line of text
to the X11 library so that it can position the window both on top
and beneath the current line of text, if needed.
* tweaking X11 CJK candidate positioning
* abandon the screen-positioning heuristic
Instead, we just send the bounding rect of the current text character
and hopefully let the X11 platform libs decide where to put the
CJK candidate popup
* add more spacing to the bounding rect on X11
* tweak for a bit more space between CJK candidate window
* more tweaks, rect height isn't being respected for some reason...
* attempting to add more instrumentation to figure out wtf is going on with X11 CJK positioning
* remove bad instrumentation that was causing freezes. ugh
* different approach for IME placement on X11
* previous positioning attempts for X11 didn't work.
New strategy: let it be positioned, and then try to move it
* still trying to fix X11 CJK candidate window positoining...
* trying to find CJK candidate window with X11 queries (To move it)
* abandon window scanning approach
* better approach, now just tweaking it
* fix one case where the candidate window was flipped but it pointing too low
* tweaking more
* trying to fix above-text line positioning
* still trying to tweak CJK candidates ABOVE the text line
* be more conservative when guessing whether X11 will show the CJK candidate above or below
* improve size heuristic for CJK candidate height
* calling X11 as complete now. jfc. Cleanup, remove debug logs, etc
* TextInput: infer soft-keyboard `input_mode` from `content_type` if its unset
New functon: `effective_input_mode()` will now derive a keyboard layout
from the `content_type`, if one was provided and if it makes sense to infer.
Explicitly setting the `input_mode` will always take precendence.
* Support standard keyboard navg shortcuts/keys in TextInput
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
* Add `CropToFill` image fit variant, improve ImageFit docs
This allows you to easily achieve the "centered cropped fit" that most apps
want for things like avatars or small thubmnails that get masked.
* Detect and support hardware keyboards, distinguish from soft/virtual kbd
Mimic desktop behavior on mobile systems as much as possible.
This is esp important for tablets like iPad OS where you're more likely
to have a real physical keyboard attached.
For iOS:
* Arrow keys and Home/End/PageUp/PageDown navigate and auto-repeat
at the system-defined rate (connected via `UIKeyCommand`)
* Cmd+Enter to submit a `TextInput` and Cmd+C/X/V clipboard shortcuts now work.
* Ensure the pop-up diacritic/accent menu is properly placed using a hidden
`UITextInput` native widget, which acts as a sort of "proxy"
* Proactively drain `ShowTextIME` after each draw so the IME position will be
properly updated after each keystroke.
* Importnatly, don't mark the IME dismissed when a hardware keyboard is attached.
For both iOS & Android:
* Add a `has_physical_keyboard()` detection mechanism across both backends,
and fix platform-specific key repeat behavior
For Android:
* Ensure clipboard cut/copy works using the same Ctrl shortcuts (API 26+)
Soft/virtual keyboard/IME changes:
* For multiline TExtInputs, a soft keyboard Enter/Return key will always just
insert a new line, to avoid complexity with keyboard shortcut cfgs.
* CJK keyboard character selection should also be properly positioned now
* minor optimization to avoid re-setting IME pos if it didn't change
* Ensure inline composition is still shown in TextInput on all platforms
This is mostly relevant when using CJK and other similar IMEs.
Previously Makepad didn't shown any "echoes" of the single latin chars
that the user would type, but it would correctly input the selected CJK
glyph. So if you typed `nihao` and then selected `你哈`, then you would
see the proper chinese characters but not the latin "nihao".
Tha't s a bit confusing while typing.
Summary of the fixes per platform:
macOS:
- `set_marked_text` now forwards the marked (composition) text to the
focused TextInput with `replace_last = true`; previously it only stored
it in an ivar. `unmark_text` clears the preview, and both it and
`insert_text` share a new `clear_marked_text_ivar` helper so a commit
doesn't emit a second, destructive text-input event.
Windows:
- Add `WM_IME_COMPOSITION` handling: commit `GCS_RESULTSTR`
(`replace_last = false`) and show `GCS_COMPSTR` inline
(`replace_last = true`), and clear on `WM_IME_ENDCOMPOSITION`. The
message is consumed so DefWindowProc neither draws its own composition
window nor synthesizes a duplicate WM_CHAR for the result.
- Extend the vendored `windows` binding with `ImmGetCompositionStringW`,
`GCS_COMPSTR`/`GCS_RESULTSTR`, and `WM_IME_COMPOSITION`/
`WM_IME_ENDCOMPOSITION`, which it didn't previously generate.
Linux (Wayland):
- Handle the `zwp_text_input_v3` `PreeditString` event (previously empty)
and apply the double-buffered preedit/commit state on `Done`, in the
protocol-mandated order (commit, then preedit), clearing the preview
when a cycle carries no preedit.
Linux (X11):
- Create the input context with XIM on-the-spot (`XIMPreeditCallbacks`)
and forward the preedit string from the draw/start/done callbacks,
falling back to `XIMPreeditNothing` if the IM server doesn't support
callbacks. Callbacks run inside `XFilterEvent`, so they only mutate a
thread-local that the event loop drains into the widget afterward,
avoiding re-entrant access to the app.
Android:
- Don't mark the IME dismissed when a physical keyboard is attached
(mirrors the iOS guard). Android was unconditionally calling
`text_ime_was_dismissed()` on soft-keyboard hide, which tore down the
IME connection that hardware-key composition relies on.
* iOS: replace custom `UITextInput` with a native `UITextView`
`UITextView` is a full system-native keyboard client, so we get all the
major features for free: language HUD pill and the complete globe/Ctrl+Space
shortcut to cycle between IMEs/languages.
Makepad basically just mirrors the state of the system native text view,
via the `full_state_sync`, but the actual native text view is kept invisible
so it doesn't interfere with what we render in Makepad's TextInput.
Notably, the Full Keyboard Accessibility setting now does work properly,
whereas it did not before with our UITextInput-based approach.
We also make sure that arrow keys, nav keys, auto-repeat, and modifiers
are properly hanlded so we can retain the expected kbd shortcuts,
like other desktop platforms.
* iOS: remove the old `UITextInput` connection with the Makepad TextInput
We've now switched to the native UITextview, so we don't need this any more.
* iOS: fix desync during fast typing
Ensure there's no race between the native UITextView and
Makepad's TextInput, as the Enter/REturn key needs special handling
w.r.t. how `pressesBegan` gets it (From a real hardware kbd).
* TextInput: more iOS integration, and text input types
more native integration for things like username/password,
new password fields, email, address, URLs, etc.
These tell iOS to change the keyboard layout/type for the text input.
* iOS: don't let Full Keyboard Access focus on our hidden native cursor
* cleanup
* iOS/TextInput: fix perf issues
* iOS TextInput: more fixes for read-only efficiency, and filtered input
Also port some of these fixes to Android's IME integration layer
* iOS/TextInput: hide the native caret iOS draws during autocorrect
but still allow the "decline autocorrect" bubble to popup where that
hidden caret is located (and the CJK candidate window in the same spot)
* Avoid script VM re-entrant panic: defer animator_cut/play if script VM is held
`animator_cut` / `animator_play` call `cx.with_vm`, which panics
(*"Script VM swapped off"*) when invoked during an apply walk — e.g. a
widget's `on_after_apply` on `ScriptReapply` / `Reload` — because the VM
is already taken for the duration of that walk's enclosing `cx.with_vm`.
- The derive macro's `animator_cut_scoped` / `animator_play_scoped` now
check `cx.is_script_vm_held()`; when held, they queue the op
(`defer_cut` / `defer_play`) and return instead of re-entering the VM.
- `animator_handle_event_scoped` replays the queue via `flush_deferred`
on the next frame, once the VM is free.
The defer path runs **only** in the formerly-panicking case, so VM-free
animations are byte-for-byte unchanged.
Also adds a re-entrancy-naming panic (`VmHolderGuard`) plus
`Cx::try_with_vm` / `Cx::is_script_vm_held` for diagnosing and handling
this class of bug.
* Better spacing/positioning for IME popups like the CJK candidate menu
applied to all platforms, but primarily an issue on macOS/iOS.
The candidate/conversion window (e.g. CJK pinyin) was covering the line of
text being composed. Carry the caret-line rect (not just a point) through
ShowTextIME and feed each backend its native "keep clear of this line" API,
so the OS places the candidate directly above/below the line with a small gap:
- macOS: firstRectForCharacterRange returns the line rect via AppKit
convertRect:toView:nil + convertRectToScreen (drops the hand-rolled
screen-coord math + fudge offsets); invalidate on caret move.
- Windows: ImmSetCandidateWindow with a CFS_EXCLUDE line rect.
- Wayland: set_cursor_rectangle with the real line rect.
- X11: XNSpotLocation/XNArea at the line.
- iOS: return the true composing-line box from firstRectForRange so iOS flips
around the real edges (consistent at any screen position) instead of a
degenerate point; only while marked text is active, to avoid an oversized
autocorrect highlight when typing normally.
* Fix Linux X11 behavior: Ctrl-based kbd shortcuts didn't work in TextInput
also trying to fix X11 behavior for positioning the CJK candidate window,
turns out there was an X11 bug for Ubuntu 22 and older so it's not always
possible, but we can attempt a workaround if errors occur (based on that,
we try to auto-detect the version of X11)
* fix X11 event loop latency by draining only a max of 64 events before redrawing
still working on X11 CJK candidate window positioning...
* add logs to X11 ime to figure out wtf is going on
* more robust fallbacks for X11 CJK candidate window positioning... grr
* maybe try to set the XFontSet attribute? for CJK candidate positioning
* positioning works now but there is a bit of overlap still
* now that X11 CJK candidate positioning works in some cases,
we need to pass the full rectangle containing the current line of text
to the X11 library so that it can position the window both on top
and beneath the current line of text, if needed.
* tweaking X11 CJK candidate positioning
* abandon the screen-positioning heuristic
Instead, we just send the bounding rect of the current text character
and hopefully let the X11 platform libs decide where to put the
CJK candidate popup
* add more spacing to the bounding rect on X11
* tweak for a bit more space between CJK candidate window
* more tweaks, rect height isn't being respected for some reason...
* attempting to add more instrumentation to figure out wtf is going on with X11 CJK positioning
* remove bad instrumentation that was causing freezes. ugh
* different approach for IME placement on X11
* previous positioning attempts for X11 didn't work.
New strategy: let it be positioned, and then try to move it
* still trying to fix X11 CJK candidate window positoining...
* trying to find CJK candidate window with X11 queries (To move it)
* abandon window scanning approach
* better approach, now just tweaking it
* fix one case where the candidate window was flipped but it pointing too low
* tweaking more
* trying to fix above-text line positioning
* still trying to tweak CJK candidates ABOVE the text line
* be more conservative when guessing whether X11 will show the CJK candidate above or below
* improve size heuristic for CJK candidate height
* calling X11 as complete now. jfc. Cleanup, remove debug logs, etc
* iOS: replace custom `UITextInput` with a native `UITextView`
`UITextView` is a full system-native keyboard client, so we get all the
major features for free: language HUD pill and the complete globe/Ctrl+Space
shortcut to cycle between IMEs/languages.
Makepad basically just mirrors the state of the system native text view,
via the `full_state_sync`, but the actual native text view is kept invisible
so it doesn't interfere with what we render in Makepad's TextInput.
Notably, the Full Keyboard Accessibility setting now does work properly,
whereas it did not before with our UITextInput-based approach.
We also make sure that arrow keys, nav keys, auto-repeat, and modifiers
are properly hanlded so we can retain the expected kbd shortcuts,
like other desktop platforms.
* iOS: remove the old `UITextInput` connection with the Makepad TextInput
We've now switched to the native UITextview, so we don't need this any more.
* iOS: fix desync during fast typing
Ensure there's no race between the native UITextView and
Makepad's TextInput, as the Enter/REturn key needs special handling
w.r.t. how `pressesBegan` gets it (From a real hardware kbd).
* TextInput: more iOS integration, and text input types
more native integration for things like username/password,
new password fields, email, address, URLs, etc.
These tell iOS to change the keyboard layout/type for the text input.
* iOS: don't let Full Keyboard Access focus on our hidden native cursor
* cleanup
* iOS/TextInput: fix perf issues
* iOS TextInput: more fixes for read-only efficiency, and filtered input
Also port some of these fixes to Android's IME integration layer
* iOS/TextInput: hide the native caret iOS draws during autocorrect
but still allow the "decline autocorrect" bubble to popup where that
hidden caret is located (and the CJK candidate window in the same spot)
* Ensure that a view that specifies Fit with a max value can be scrolled.
* Turtle: include a view's outer maring in the size calc for a `Fit{max}` bound.
* Modal: dismiss on Escape KeyUp (not KeyDown) so the release can't leak to a
background widget behind the modal.
* Modal: allow scrolling, and reset the scroll to the top when showing it.
* Touch-baased dragging for views (ScrollBar) and PortalList now respect
the blocked scrolling areas, not just the mouse wheel / trackpad scroll.
* Forward the `set_scroll_pos()` through the widget derive traits so that
we don't have to hook it up for each specific widget.
* Image support: add bmp/qoi,ico, webp, SVG in `Image` widget, 16-bit png
Generally, this commit makes improvements to image decoding and rendering.
Added a bunch of functions for image discovery / metadata gathering:
`decode_image_from_data()`, `image_size_by_data()`, `looks_like_svg()`
Added more `Image[Ref]` functions for other image formats:
`ImageRef::load_{bmp,qoi,ico,gif,webp,svg}_from_data()`, plus a nice
convenience fn for auto-detec+load: `load_image_from_data()`.
Added cheap, lazily-init'd support for SVGs within the `Image` widget.
Fixed some issues with aspect ratio being clobbered during image rotation.
* Audit and harden image decoding stuff against huge inputs (DoS)
Bound the size of the decoded image, pixel count, frame counts (for animated),
range of SVG sniffing, and encoded file size.
Only once we run those checks do we actually alloc a buffer for the decoded image. before allocating decode buffers. Validate
Add various other checks within the vendored image decoding libraries too.
Generally, this commit makes improvements to image decoding and rendering.
Added a bunch of functions for image discovery / metadata gathering:
`decode_image_from_data()`, `image_size_by_data()`, `looks_like_svg()`
Added more `Image[Ref]` functions for other image formats:
`ImageRef::load_{bmp,qoi,ico,gif,webp,svg}_from_data()`, plus a nice
convenience fn for auto-detec+load: `load_image_from_data()`.
Added cheap, lazily-init'd support for SVGs within the `Image` widget.
Fixed some issues with aspect ratio being clobbered during image rotation.
* Support standard keyboard navg shortcuts/keys in TextInput
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
* Add `CropToFill` image fit variant, improve ImageFit docs
This allows you to easily achieve the "centered cropped fit" that most apps
want for things like avatars or small thubmnails that get masked.
* Detect and support hardware keyboards, distinguish from soft/virtual kbd
Mimic desktop behavior on mobile systems as much as possible.
This is esp important for tablets like iPad OS where you're more likely
to have a real physical keyboard attached.
For iOS:
* Arrow keys and Home/End/PageUp/PageDown navigate and auto-repeat
at the system-defined rate (connected via `UIKeyCommand`)
* Cmd+Enter to submit a `TextInput` and Cmd+C/X/V clipboard shortcuts now work.
* Ensure the pop-up diacritic/accent menu is properly placed using a hidden
`UITextInput` native widget, which acts as a sort of "proxy"
* Proactively drain `ShowTextIME` after each draw so the IME position will be
properly updated after each keystroke.
* Importnatly, don't mark the IME dismissed when a hardware keyboard is attached.
For both iOS & Android:
* Add a `has_physical_keyboard()` detection mechanism across both backends,
and fix platform-specific key repeat behavior
For Android:
* Ensure clipboard cut/copy works using the same Ctrl shortcuts (API 26+)
Soft/virtual keyboard/IME changes:
* For multiline TExtInputs, a soft keyboard Enter/Return key will always just
insert a new line, to avoid complexity with keyboard shortcut cfgs.
* CJK keyboard character selection should also be properly positioned now
* minor optimization to avoid re-setting IME pos if it didn't change
* video_debug
* Fix video pause being overridden by stall-recovery force-play on macOS
The native AVPlayer poll loop nudged a rate-0 player back into playing
whenever `autoplay` was true, intended as stall recovery but firing every
frame after a user-initiated pause. Once `begin_playback` latched
`autoplay = true` on first start, subsequent pauses were undone on the
next frame poll.
Split user playback intent into a `should_play` field that toggles on
play/pause/resume, and gate the force-play check on that instead of
`autoplay` (which is now a one-shot consumed in `check_prepared`).
Also restore the `Apply::Animate` early return in `Video::on_after_apply`
(needed so hover transitions don't re-decode the PNG/JPG thumbnail every
frame) and drop the redundant `Texture::new(cx)` allocation in
`apply_thumbnail_settings` that load_thumbnail_image immediately
overwrote anyway.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Support standard keyboard navg shortcuts/keys in TextInput
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
* Add `CropToFill` image fit variant, improve ImageFit docs
This allows you to easily achieve the "centered cropped fit" that most apps
want for things like avatars or small thubmnails that get masked.
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
Remove the concept of a "full-screen" override for stack nav,
as it's completely useless and just added complexity.
This also fixes the push/pop "sliding" animation to be more fluid
* Dock: avoid ID collisions in drag/drop; never delete dock root in unsplit_tabs
* Clean up and further harden dock logic around splitting/dragging
* cargo_makepad: Android App Bundle builds, API 26 support, stable toolchain
Overhaul the Android build pipeline. Three related build-tooling
changes that share compile.rs/sdk.rs and so are committed together.
Android App Bundle (.aab) support — required for Google Play uploads:
- New `build-aab` command: compile resources with aapt2, link a
proto-format APK, assemble the base module, run bundletool, and sign
with jarsigner.
- New `keystore-create` command wrapping keytool, with a reusable
keystore sidecar file; new `--keystore*`, `--no-sign`,
`--version-code`, `--version-name` flags.
- Version codes may be explicit or auto-generated as a monotonic
YYYYMMDDHH UTC integer.
- Read app id, version, and signing metadata from
`[package.metadata.packager]` / `[package.metadata.makepad.android]`
in Cargo.toml; support a custom AndroidManifest.xml template.
- Upgrade the bundled TOML parser for the dotted keys, inline tables,
and multi-line strings those metadata sections use.
- Download bundletool and copy jarsigner/keytool/aapt2 into the SDK.
minSdkVersion 26:
- Lower the default Android minimum SDK from 33 to 26 and track the
target SDK (35) separately, emitting minSdkVersion and
targetSdkVersion independently in the generated manifest; add a
`--min-sdk-version` override.
Stable Rust toolchain:
- Build Android and iOS on stable instead of nightly. tvOS still needs
nightly for `-Z build-std`, so the channel is resolved per target.
- Add `ensure_rust_toolchain_installed` (install only when missing).
* Android: load newer NDK symbols at runtime to support API 26
With the minimum SDK lowered to 26, NDK entry points that only exist
on newer API levels can no longer be declared with `extern "C"` —
doing so breaks `dlopen`/startup on API 26-28. Resolve them at
runtime instead:
- amidi_sys: lazily `dlopen` libamidi.so (API 29+) into a cached
vtable; the wrappers degrade to error/zero returns when the library
is absent on older devices.
- android_jni: `dlsym` the AChoreographer vsync callbacks, gated on
the running API level.
- ndk_sys: drop the `extern "C"` declarations for
`ANativeWindow_setFrameRate` and the Choreographer callbacks;
android.rs drops the now-unused frame-rate call.
- MakepadActivity: guard `setInitialSurroundingSubText` (API 30+) and
`layoutInDisplayCutoutMode` (API 28+) behind version checks.
- android_jni: the fallback render-loop thread now exits cleanly when
the app is torn down.
* Android: automatic and app-controlled system bar appearance
Add a way to control the tint of the status and navigation bar icons,
fixing white-on-white (invisible) icons when an app draws a light
background under a system dark-mode theme.
- New `Cx::set_system_bar_appearance(SystemBarAppearance)`. The default
`Auto` mode picks dark or light icons from the window background
luminance; `DarkIcons`/`LightIcons` force the choice.
- The `Window` widget resolves the setting each event cycle — for
`Auto`, the Rec.709 luma of `pass.clear_color` — and emits
`CxOsOp::SetSystemBarDarkIcons` only when the resolved value changes.
- On Android this drives `WindowInsetsController.setSystemBarsAppearance`
(API 30+) or the `SYSTEM_UI_FLAG_LIGHT_*` flags (API 26-29). The tint
is re-asserted after fullscreen toggles, since the legacy path
rewrites the whole `systemUiVisibility` bitmask.
* Android: fix soft-keyboard handling and edge-to-edge insets
Several related window-inset and IME fixes, mostly affecting devices
that are not edge-to-edge (Android versions before 15).
- Report safe-area and IME insets as the overlap with the render
surface, not the raw window-edge insets. On a non-edge-to-edge
window the surface already sits inside the system bars, so the raw
insets double-counted — leaving oversized gaps around content and
above the keyboard.
- Also drive safe-area insets from `onGlobalLayout`, so the app is
inset correctly from launch instead of drawing under the status bar
until the first keyboard show or rotation.
- While the keyboard animates, treat the `WindowInsetsAnimation`
callback as the authoritative per-frame inset source and have the
layout-driven callbacks defer to it. Read target IME visibility from
`getRootWindowInsets()` so a show animation is not misread as an
instant dismissal.
- Only reconfigure the Java IME when the `TextInputConfig` actually
changes, instead of on every show.
- `KeyboardView`: compute and apply the content shift at keyboard-show
event time, removing a one-frame lag and a tail-end jump; only
reconcile post-draw when the focused field actually redrew.
- `Modal::close()`: skip the focus revert when the modal is already
closed — it was stealing focus from a just-tapped text input and
causing a first-tap keyboard flicker.
- Hide the keyboard via `WindowInsetsController.hide(ime())` on API 30+.
* platform: don't panic posting actions during shutdown
post_action no longer unwraps the global action sender. It now
silently drops the action if the sender mutex is poisoned, no Cx
sender is installed, or the receiver has been dropped during app
teardown, and only raises the UI signal when the send succeeds.
(Also shortens an over-long field doc comment in cx.rs; no behavior
change.)
* cargo-makepad: link std statically in AAB builds (16 KB page-size fix)
`-C prefer-dynamic` ships std as a separate, 4 KB-aligned libstd.so that
fails Play's 16 KB page-size rule. AAB builds now link std statically;
APK/dev builds keep prefer-dynamic. Also documents {min_sdk_version} in help.
* Disable SLUG text band acceleration
* Load Android optional APIs dynamically
* Fixed the android-only Gauss-pane vertical flip by correcting render-target Y sampling in:
- widgets/src/window.rs:110
- widgets/src/gauss_view.rs:151
Root cause: Gauss captures the scene into render-target textures, then samples them back
into the UI. Those render-target textures need a Y flip when displayed, matching the
existing Image widget behavior.
* Support overriding the dpi factor at runtime, on all platforms
Add `Cx::set_window_dpi_override` for runtime UI zoom, but dispatch it
in a deferred manner so it's safe to call in an event handler.
For each platform, we connect the dpi override to the click/tap
coordinates to remap it properly, which was done on some platforms
but not most.
* Fix and restyle todo example
* cad
* Fix todo input styling and studio build env
* fix slides
* Don't apply UI scaling (dpi override) to safe inset areas / IME areas
Scaling those areas doesn't make sense, as it can lead to empty space
(extra unnecessary padding) on the border of the IME or the device inset area,
which looks bad and is basically objectively wrong
-------------
Centralize native/physical/layout DPI conversion on `CxWindow`, and use it at platform boundaries for window geometry, safe-area insets, input coordinates, soft keyboard spacing, clipboard and selection overlays, and camera preview rects.
Add runtime `set_window_dpi_override` support that rescales all window-local metrics and emits `WindowGeomChange`.
* Improve mobile IME and soft keyboard handling
- Add broader soft keyboard configuration for input modes, autocorrect, autocapitalization, return key types, multiline, and secure text entry.
- Improve iOS text input state handling, composition ranges, selection sync, and native/layout coordinate conversion.
- Improve Android InputConnection handling for composing text, selection updates, batch edits, editor actions, surrounding text, and programmatic text sync.
- Wire TextInput through the expanded IME configuration surface.
- Cover newer iOS and Android IME APIs while preserving fallbacks for older keyboard behavior.
* Fix iOS IME area DPI override scaling
* Remove Android-specific IME hack
* Further fix Android IME to avoid stale composition ranges being underlined
espeically after you tap elsewhere in the TextInput widget
---------
Co-authored-by: admin <info@makepad.nl>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Don't apply UI scaling (dpi override) to safe inset areas / IME areas
Scaling those areas doesn't make sense, as it can lead to empty space
(extra unnecessary padding) on the border of the IME or the device inset area,
which looks bad and is basically objectively wrong
-------------
Centralize native/physical/layout DPI conversion on `CxWindow`, and use it at platform boundaries for window geometry, safe-area insets, input coordinates, soft keyboard spacing, clipboard and selection overlays, and camera preview rects.
Add runtime `set_window_dpi_override` support that rescales all window-local metrics and emits `WindowGeomChange`.
* Fix pre-existing iOS and Android build breaks
iOS (platform/src/os/apple/ios/ios.rs): five `CxOsOp` arms had edits
that landed one match-arm late, so each block referenced bindings only
in scope on the preceding arm. Re-home them:
- `WindowGeomChange` now applies `native_window_geom_to_layout` (the
two stray lines previously sat inside the `Paint`/`prepared` arm).
- `ShowTextIME` now converts `pos` via `layout_vec2d_to_native_points`
(previously lodged inside the `SyncImeState` destructure pattern).
- `ShowClipboardActions` now converts `rect` / `keyboard_shift` to
native points (previously appended to `ShowSelectionHandles`).
- `ShowSelectionHandles` / `UpdateSelectionHandles` now convert `start`
and `end` (the `Update` arm had no conversion, and the `Show` arm's
conversion was actually the clipboard one).
- `FullscreenWindow` / `NormalizeWindow` drop the bogus `start` / `end`
conversions that didn't belong there.
Android (platform/src/ime.rs): `android_jni::to_java_configure_keyboard`
matches on `InputMode::None` and `ReturnKeyType::{Next, None, Previous,
Google, Yahoo, Join, Route, Continue, EmergencyCall}` — variants that
exist on the `ime_improvements` branch (commit 3dc039f0a) but weren't
pulled into this branch. Add them to the enum definitions so the
android target compiles.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This normalizes the IME geometry calcs across iOS and Android.
The main difference is to make KeyboardView shift the content based on
the focused TExtInput instance instead of trying to shrink the viewport.
Also make sure that StackNavigation widget properly handles the
keyboard shift, even when it is drawing in full-screen mode.
* App menu bar: restore Quit option, use proper app name
The menu bar shows "MakepadStdInLoop" by default, which is really strange
especially for published apps. This fixes that and also allows the app
to set the name, as well as using a sensible default for it if the app
didn't specify it.
We also now restore the previous Makepad 1.0 behavior of having a default
"Quit" entry in the main app's first menu bar entry.
* ensure Exit flow actually makes it out, on macOS
* WIP: adding full app lifecycle event support, and Ctrl+C/signal catch
* Added fuller lifecycle event support, plus ability to catch sigquit
Tested working well on every platform except web/wasm, as I don't have
a working setup able to test that.
* Fix portallist alignment handling so centering actually works
Now, alignment on PortalLists now only applies to the "cross-axis"
of each item, not the main axis.
So when you center a portallist itself, it won't add weird space
on the leading side of the list
* Fix text not drawing on top of a background, e.g., `<code>` tags
This worked in *most* but not all cases, e.g., if you had a ton of
inline code tags, some of them would rarely but deterministically
not show the actual text glyphs, but just an empty background.
* Avoid large margin on the left of `<code>` if it's on a new line
* Add a separate "touch" margin; use it on dock splitter and tab close
Without this, those dock UI elements are nearly impossible to grab
and press on a real touch screen device, even on my iPad.
Also, tweak cargo-makepad iOS and Android builds to use a polished
display name for the app (uppercase first character) by default.
* Fix portallist alignment handling so centering actually works
Now, alignment on PortalLists now only applies to the "cross-axis"
of each item, not the main axis.
So when you center a portallist itself, it won't add weird space
on the leading side of the list
* Fix text not drawing on top of a background, e.g., `<code>` tags
This worked in *most* but not all cases, e.g., if you had a ton of
inline code tags, some of them would rarely but deterministically
not show the actual text glyphs, but just an empty background.
* Avoid large margin on the left of `<code>` if it's on a new line