fix: Linux/WebKitGTK image intake — file picker, clipboard paste, and drop-zone claim - #3124
Conversation
|
Thanks for the fix. Before merging, please address the remaining integration issues:
After these are addressed, this should be ready for another review. |
The composer's Add-image flow created a detached <input type=file> and clicked it. On WebKitGTK (Linux) the native chooser opens, the user picks a file, and the engine never fires change on the detached input, so every selection was silently dropped - no thumbnail, no log, no error. WebView2 and WKWebView deliver change either way, which is why only Linux users hit this. Mount the picker offscreen before clicking it (display:none is avoided on purpose: some WebKit builds refuse to open a chooser for it), and reclaim the node on both the change path and the cancel path via a one-shot window focus listener. Verified on Linux/WebKitGTK 2.52 with an isolated desktop instance: picker selection now lands in the composer.
WebKitGTK delivers paste events with empty DataTransfer items and types, and its Async Clipboard API promise never settles, so a pasted image was unreachable from the page: the composer's file branch never ran and the paste landed as nothing. Add a get_clipboard_image desktop command that reads the clipboard through the same wl-paste/xclip tools as get_clipboard_files, sniffs magic bytes, and returns base64 pixels. The composer now listens for paste directly and, only when the webview reported zero types (the WebKitGTK shape; WebView2 and WKWebView deliver images in-band), asks the host for the image and reuses the existing clipboard-image intake with identical limits and errors. Registers the command in the remote-surface registry (LocalOnly) and in the attachments capability evidence; regenerates the capability artifacts.
ContextDropZone called preventDefault on every dragenter/dragover, which turned the composer into a DOM drop target for OS file drags. On WebKitGTK an OS file drag reports no dataTransfer types, so once the zone was claimed, the in-page handler saw nothing to handle while the claim itself interfered with the drag pass-through. Claim only drags the zone can positively identify and handle: internal context payloads, typed non-file drags, and Files drags when a DOM file handler is actually provided (the Windows desktop runtime). Empty-typed drags stay unclaimed and keep flowing to the pane-level native drop path. Known limitation: with this change the zone no longer swallows empty-typed drags, but dropping an OS file directly on the composer still does not attach on WebKitGTK 2.52 - a document-level dragover preventDefault keeps the subtree claimed and the native window drop handler still never sees the release over the composer. Drops elsewhere in the conversation pane work. Full on-composer native drops need follow-up at the WebKitGTK/wry interaction level.
Review follow-up for the WebKitGTK clipboard-image fallback: - get_clipboard_image now distinguishes "clipboard holds no image" from "neither wl-paste nor xclip could be spawned". The latter returns an explicit clipboard_image_unsupported error that the composer surfaces as a localized warning instead of silently doing nothing. - Linux clipboard tool spawns go through the repository process-manager facade (openbitfun_core::util::process_manager::create_command) instead of bare std::process::Command, matching the repo rule for GUI-hosted child processes.
2f9b9f8 to
610801c
Compare
|
1. 1. Missing wl-paste/xclip is now an explicit unsupported state. 2. Process-manager abstraction. All Linux clipboard tool spawns — the new image readers and the pre-existing 3. Rebased onto latest 4. Screenshots on Ubuntu 26.04 / GNOME Wayland / WebKitGTK 2.52.6 (attached):
Focused suites: desktop clipboard API 14/14, web-ui intake/drop-zone tests 9/9. As with #3123, fork-PR checks need a maintainer workflow approval to run. |


Summary
On Linux (WebKitGTK 2.52.x), images could not be inserted into the chat
composer at all: the "Add image" picker silently dropped every selection,
and pasting a screenshot did nothing. Both paths are now fixed and verified
on real hardware; a third, partial improvement un-claims the composer drop
zone for unidentified drags.
All three failures are WebKitGTK-specific engine gaps, not regressions in
this repo — WebView2 and WKWebView never hit them, which is why they went
unnoticed upstream.
Root causes (probed on WebKitGTK 2.52.6 / GNOME 50.1 / Wayland)
File picker — detached
<input type=file>never receiveschange.The picker was created via
createElementand clicked without beingmounted. WebKitGTK opens the native chooser, the user picks a file, and
the engine never fires
changeon the detached element — the selectionis silently dropped (no thumbnail, no log, no error). Verified with a
minimal GTK+WebKit probe: attached inputs fire
change; detached onesdo not.
Paste —
DataTransferis permanently empty.WebKitGTK delivers
pasteevents with zeroitemsand zerotypes(even for text), while
getData()keeps working — so text paste worksbut the in-page file branch can never see an image. The Async Clipboard
API (
navigator.clipboard.read()) is not a way out either: its promisenever settles on this engine. Pasted images were simply unreachable
from the page.
Drag & drop — the composer drop zone claims unidentified drags.
ContextDropZonecalledpreventDefaulton every dragenter/dragover.On WebKitGTK an OS file drag reports no types at all, so the claim
swallowed the drag while the in-page handler found nothing to handle.
(Partial fix — see "Known limitations".)
The commits
fix(web-ui): mount the image picker so WebKitGTK delivers changeMounts the picker offscreen (
position: fixed; left: -9999px—display: noneis deliberately avoided because some WebKit builds refuseto open a chooser for it) and reclaims the node on both the change path
and the cancel path (one-shot window
focuslistener).fix(desktop): read pasted clipboard images through the host on WebKitGTKAdds a
get_clipboard_imagedesktop command that reads the clipboard viathe same
wl-paste/xcliptools already used byget_clipboard_files,sniffs PNG/JPEG magic bytes, and returns base64 pixels. The composer now
listens for
pastedirectly and — only when the webview reported zerotypes (the WebKitGTK shape; WebView2/WKWebView deliver images in-band and
keep their existing path) — asks the host for the image and reuses the
existing clipboard-image intake, so limits and error reporting are
identical. Registers the command in the remote-surface registry
(
LocalOnly) and in theattachmentscapability evidence; capabilityartifacts regenerated.
fix(web-ui): stop claiming empty-typed drags in the composer drop zoneThe zone now claims only drags it can positively identify and handle:
internal context payloads, typed non-file drags, and
Filesdrags when aDOM file handler is actually provided (the Windows desktop runtime).
Empty-typed drags stay unclaimed and keep flowing to the pane-level
native drop path.
Verification
Real device: Ubuntu 26.04, GNOME 50.1, Wayland, WebKitGTK 2.52.6, deb
install shape.
+→ Add image → pickerdesktop instance: synthetic empty-typed
pasteon the composer →host clipboard read → attachment thumbnail rendered.
picker, the paste fallback gating, and the unclaimed drag), desktop
clipboard API 14/14, product-domains registry 40/40,
check:core-boundariesgreen,capabilities:generateregenerated.Known limitations
on WebKitGTK: a document-level
dragoverpreventDefaultkeeps thesubtree claimed and the native window drop handler never sees the
release over the composer. The third commit removes the zone's own
silent swallow and is a step toward the fix, but full on-composer
native drops need follow-up at the WebKitGTK/wry interaction level.
changefires fine there;DataTransfershape is synthetic), so thenew tests lock in the wiring and the gating decisions, and the real
verification is the on-device matrix above.
Platform impact
No behavior change on Windows or macOS: WebView2/WKWebView populate
DataTransferand deliverchangefor detached inputs, so the fallbackpaths never trigger and the in-band paths are untouched.