Repository navigation
Android: touch, soft keyboard and phone-width issues found testing every component of 0.7.0 #3310
Description
Description
Thank you for GPUI Kit. I built an on-device test gallery for GPUI Kit v0.7.0 on Android (gpui-mobile host entry point, a SurfaceView Activity, phone in portrait) with a demo screen for every user-facing component, and went through each one by touch. Most components work well; this issue collects what does not, in case it helps. I'm happy to split it into focused issues, add details or recordings, or test fixes on the device. Full per-component notes are in the gallery's COMPONENT_MATRIX.md (77 working / 18 partial / 4 broken / 4 not applicable), and the APK is on the v0.1.2 release.
Fixes already proposed (one PR per repository):
- Slider cannot be dragged by touch → slider: Let a touch drag on the track move the thumb #3313 (merged)
- gpui-fps HUD panics on Android (
monospacefont does not exist) → slider: Let a touch drag on the track move the thumb #3313 (merged) - gpui-mobile: clipboard never reaches the system → android: Use the system clipboard, and only tear down the surface a destroy names gpui-mobile#24
- gpui-mobile: black screen after Activity recreation (late
surfaceDestroyed) → android: Use the system clipboard, and only tear down the surface a destroy names gpui-mobile#24
Try it on a device
The test app is open source and meant to be used as a playground: Bombatomica64/Gpui-android.
- Prebuilt APK (arm64-v8a + x86_64, sideloadable, signed with a debug key): gpui-kit-mobile-lab-v0.1.2.apk
- Build from source:
./build.sh android --release --install(Rust + cargo-ndk + Android SDK/NDK; see the README). - Each component has its own screen with its states, current value and an event log; there are also Touch Lab, Scroll Stress, Diagnostics, Stress Test and Themes screens. To try a Kit change on Android, add the changed Kit crates (e.g.
gpui-base = { path = "…/gpui-kit/crates/base" }) to the[patch.crates-io]section of itsCargo.tomland rebuild. The app is on Kit 0.7.0 /gpui-pre0.3.7, so the patched crates need to stay on that GPUI snapshot.
Environment
- GPUI:
gpui-pre0.3.7 (the snapshot Kit 0.7.0 pins),wgpu29.0.4 - GPUI Kit: 0.7.0 (
0c830f4d) - gpui-mobile:
f379bc8(plus the patches above) - Platform: Android 13 (API 33) on Redroid, 1080×2340 at 420 dpi (411×819 pt, scale 2.625), AOSP keyboard. Interactions were driven with
adb shell input(taps, swipes, rawmotioneventsequences, IME typing). SwiftShader rendering, so no performance claims.
Steps to Reproduce
Install the release APK and open a component's screen from the catalog, or directly:
adb shell am start -n dev.gpui.mobile.lab/.LabActivity --es screen "'Number & OTP'"Each screen shows the current value and an event log (also on logcat, tag GPUI_MOBILE_LAB).
Actual
Broken on a touch-only device
- OtpInput and TimeField (and the time part of a date+time
DatePicker): tapping shows no soft keyboard. They have no text-input handler (EntityInputHandler) and never request the virtual keyboard, so they can only be edited with a hardware keyboard. - Context menus (
ContextMenuExt) open only on the right mouse button; a long-press does nothing, so there is no way to open one on a phone.LongPressEvent(claimed withprevent_defaultonStarted) looks like the natural mapping. - Everything built on
on_dragignores finger drags, because GPUI's drag-and-drop is mouse-only and a touch drag arrives asTouchDragEvent: Resizable dividers, Dock splitters and tab drag/split, DataTable column resize/reorder. The Slider PR shows one way to handle it for a single component.
Layout at phone width (411 pt)
- Popover near the right edge and PopupMenu submenus are not moved back into the viewport and are clipped.
- Breadcrumb never wraps; the last items are clipped.
- Full Pagination overflows (Next is clipped); the compact variant fits.
- Static
Tableclips its last column (no shrinking or horizontal scroll). DescriptionListhorizontal two-column layout andSettingscontent break words mid-word; the Settings sidebar takes about 70% of the width.- Accordion: a long title does not wrap and pushes the chevron out of view.
- Carousel: prev/next buttons render outside the card and are clipped at the screen edges.
Touch behaviour
- Carousel: one fling skips several slides, because every momentum scroll delta counts as a step.
- Kit's scroll containers do not set
restrict_scroll_to_axis(), so a horizontal pan on a vertical-only list scrolls it vertically (GPUI converts the pan). Setting it on the app's own containers fixes it there. - TextView long-press selection shows handles and Copy / Select All, but the initial selection is often not the pressed word (collapsed, or starting mid-word).
- DataTable emits a stray
RightClickedRow(None)on a plain tap. - After a tap, the touched menu/list row keeps its hover highlight until the next touch elsewhere.
- Nothing scrolls a focused input above the soft keyboard; the app has to do it.
Not Android-specific
Split into focused issues:
- RadioGroup: a disabled Radio item can still be selected #3324: RadioGroup, a disabled Radio item can still be selected (fix: radio: Keep a disabled Radio disabled inside a RadioGroup #3331)
- Textarea: rows(n) does not set the height of a plain multi-line Textarea #3325: Textarea,
rows(n)does not set the height of a plain multi-line Textarea (fix: input: Make rows set the height of a plain Textarea again #3330) - Bubble: TextView inside a Filled bubble ignores the bubble text color (white on white in dark mode) #3326: Bubble, TextView inside a Filled bubble ignores the bubble text color (fix: text_view: Follow the container's text color so rich text reads in filled bubbles #3329)
- ShimmerText: default highlight is invisible on foreground text in dark mode #3327: ShimmerText, default highlight is invisible on foreground text in dark mode (fix: shimmer: Keep the default highlight visible on foreground text in dark mode #3328)
gpui-mobile integration (listed for completeness; they may belong in gpui-mobile)
- Bold and italic text render as regular weight: Android's Roboto is a variable font and the text system does not apply weight/italic variations. Headings are larger but not bold.
- Dismissing the IME with back injects an
escapekeystroke, which apps also handle as navigation/close. NumberInputand numeric masks open the full text keyboard; gpui-mobile always requests the default keyboard type.show_soft_keyboardis a no-op, so components that call it get no keyboard.- On the host-driven entry point, night mode is not reported to
window.appearance(), and the bundled-emoji fallback cannot read APK assets (it needs anAndroidApp); without a host workaround, emoji do not render on Android 13+. - Closing a sheet while a fling is still running hands the remaining momentum to the page behind it.
window.request_animation_frame()panics when called outside rendering (e.g. in a click handler).
Expected
Components are usable by touch alone: text-like fields raise the soft keyboard, context menus and drag interactions have touch equivalents, and popovers and wide components stay inside a phone-width viewport.
The gallery and this report were produced with AI assistance (Claude Code), and every item was reproduced on the emulated device.
🤖 Generated with Claude Code
Activity
Bombatomica64 commentedon Sep 29, 2026
A small update after checking the app on a physical phone (360×736 pt, dark mode): I added two items under Not Android-specific:
TextViewinside aFilledBubblerenders white on white, because TextView paints the themeforegroundover the bubble'sprimary_foregroundShimmerTexthighlight is invisible onforegroundtext in dark modeBoth include the cause and a workaround. The playground APK is now v0.1.1. Thanks again for the library!
slider: Let a touch drag on the track move the thumb (#3313)
huacnlee commentedon Sep 30, 2026
#3313 is merged as 9c369db. Main now contains the Slider touch-drag path and Android FPS font fix; these are after the v0.7.0 tag.
The rest of this report is still open. In particular, current source still overwrites each Radio's disabled state with the RadioGroup state, and the dark-mode ShimmerText default still mixes foreground text toward the same foreground color. Those are desktop-relevant too.
Please split the remaining reproducible items into focused issues, starting with disabled RadioGroup items, Textarea rows, Bubble/TextView contrast and ShimmerText contrast. That will let each fix be verified independently of the Android integration work.
Bombatomica64 commentedon Sep 30, 2026
Thank you for merging #3313 and for the guidance! I've split out the four you mentioned, each with a repro against
main(201b55a4):#[gpui_kit::test])rows(n)does not set the height of a plain multi-line Textarea (confirmed with a#[gpui_kit::test]:rows(1)androws(5)are both 38px)I'll continue with the remaining items the same way, each with its own repro, and keep this issue as the index.
huacnlee commentedon Sep 30, 2026
Bombatomica64 commentedon Sep 30, 2026
Fixes are now up for all four split issues, each with a regression test that fails on
main:rows; the root cause wasupdate_auto_growoverwritingrowsfor non-auto-grow inputs)BubbleVariant::text_view_style)Each issue has a comment with the details, including two corrections to my original reports. The playground APK is now v0.1.2.
shimmer: Keep the default highlight visible on foreground text in dar…
android: Use the system clipboard, and only tear down the surface a d…