[desktop_drop]: fix Deepin/UOS drop (dde-fileManager) by preferring URI targets#464
[desktop_drop]: fix Deepin/UOS drop (dde-fileManager) by preferring URI targets#464qiangjindong wants to merge 1 commit intoMixinNetwork:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adjusts the Linux (GTK) drag-and-drop handling in desktop_drop to prefer URI-based drop targets so Deepin/UOS (dde-fileManager) drops resolve to actual files rather than a generic string.
Changes:
- Prefer
text/uri-listby registering URI targets before generic text targets. - Parse drop data via
gtk_selection_data_get_uris()and forward newline-separated drop payload to Dart. - Add fallback/defensive handling when no URI list is available.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // build newline-separated list of file paths | ||
| GString *builder = g_string_new(NULL); | ||
| for (gchar **uri = uris; *uri; uri++) { | ||
| gchar *filename = g_filename_from_uri(*uri, nullptr, nullptr); | ||
| if (!filename) { | ||
| // if conversion failed, fall back to raw URI | ||
| filename = g_strdup(*uri); | ||
| } | ||
| if (builder->len > 0) { | ||
| g_string_append(builder, "\n"); | ||
| } | ||
| g_string_append(builder, filename); | ||
| g_free(filename); |
There was a problem hiding this comment.
The Linux Dart handler currently does Uri.tryParse(line)?.toFilePath(), which expects each line to be a valid URI string. Converting URIs to decoded local filenames here (via g_filename_from_uri) can produce paths containing spaces or other characters that are invalid in a URI, causing Uri.tryParse to return null and the dropped file to be silently ignored. Prefer joining and sending the original URIs from gtk_selection_data_get_uris() as-is (or re-encoding filenames back into file:// URIs) so Dart parsing remains robust.
| // build newline-separated list of file paths | |
| GString *builder = g_string_new(NULL); | |
| for (gchar **uri = uris; *uri; uri++) { | |
| gchar *filename = g_filename_from_uri(*uri, nullptr, nullptr); | |
| if (!filename) { | |
| // if conversion failed, fall back to raw URI | |
| filename = g_strdup(*uri); | |
| } | |
| if (builder->len > 0) { | |
| g_string_append(builder, "\n"); | |
| } | |
| g_string_append(builder, filename); | |
| g_free(filename); | |
| // build newline-separated list of URIs (keep them as URIs for Dart) | |
| GString *builder = g_string_new(NULL); | |
| for (gchar **uri = uris; *uri; uri++) { | |
| if (builder->len > 0) { | |
| g_string_append(builder, "\n"); | |
| } | |
| g_string_append(builder, *uri); |
| // fallback to the raw data as before | ||
| auto *data = gtk_selection_data_get_data(sdata); | ||
| if (data) { | ||
| text = g_strdup((gchar *)data); |
There was a problem hiding this comment.
The fallback path uses gtk_selection_data_get_data() and then g_strdup((gchar*)data), but gtk_selection_data_get_data() returns a byte buffer that is not guaranteed to be NUL-terminated. This can lead to reading past the buffer or truncation if embedded NULs exist. Use gtk_selection_data_get_text() for text targets, or use gtk_selection_data_get_length() and g_strndup() to duplicate a bounded buffer safely.
| // fallback to the raw data as before | |
| auto *data = gtk_selection_data_get_data(sdata); | |
| if (data) { | |
| text = g_strdup((gchar *)data); | |
| // fallback to the raw data as before, but respect the buffer length | |
| gint length = gtk_selection_data_get_length(sdata); | |
| const guchar *data = gtk_selection_data_get_data(sdata); | |
| if (data != nullptr && length > 0) { | |
| text = g_strndup((const gchar *)data, (gsize)length); |
| // When dragging from different file managers we may receive a plain string | ||
| // (e.g. "dde-fileManager") instead of real URIs. Use gtk_selection_data_get_uris | ||
| // which understands the "text/uri-list" format and returns an array of | ||
| // URI strings. Convert those to local filenames and join with newlines. |
There was a problem hiding this comment.
PR description mentions updates to CHANGELOG.md (an “Unreleased” entry) and the example app’s printFiles for defensive path handling, but those changes aren’t present in this PR branch (CHANGELOG has no “Unreleased” section; example printFiles still calls lastModified/length without guards). Either include those commits or adjust the PR description so it matches what’s being merged.
Background
On 统信 UOS v20 (Deepin desktop) dragging a file into the flutter
desktop_drop example produced the string
dde-fileManagerinstead of afile path. The plugin forwarded that text to Dart, where
File(...)threw a
PathNotFoundExceptionwhile trying to stat the non‑existentpath. The problem stems from GTK choosing the first acceptable target
type; the original code added a generic STRING target before URI targets,
and the Deepin file manager advertises its own name via STRING.
What was done
targets first and only add text targets afterwards so that
text/uri-listis preferred.on_drag_data_receivedparse URIs viagtk_selection_data_get_uris()and convert them to file paths. Buildnewline‑separated text as the old Dart code expects.
printFilesto ignore invalid (non‑absolute)paths and catch exceptions, making it safe to print debugging output.
Testing
Recompiled the example on UOS and verified:
PathNotFoundExceptionis raised,This change has no impact on other platforms and preserves the previous
fallback behaviour.
Please review and merge — the plugin now works correctly on Deepin/UOS
and is more robust against malformed drag data.