Skip to content

[desktop_drop]: fix Deepin/UOS drop (dde-fileManager) by preferring URI targets#464

Open
qiangjindong wants to merge 1 commit intoMixinNetwork:mainfrom
qiangjindong:fix/linux-deepin-drop-path
Open

[desktop_drop]: fix Deepin/UOS drop (dde-fileManager) by preferring URI targets#464
qiangjindong wants to merge 1 commit intoMixinNetwork:mainfrom
qiangjindong:fix/linux-deepin-drop-path

Conversation

@qiangjindong
Copy link

Background

On 统信 UOS v20 (Deepin desktop) dragging a file into the flutter
desktop_drop example produced the string dde-fileManager instead of a
file path. The plugin forwarded that text to Dart, where File(...)
threw a PathNotFoundException while trying to stat the non‑existent
path. 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

  • Remove explicit STRING target from gtk_drag_dest_set(), add URI
    targets first and only add text targets afterwards so that
    text/uri-list is preferred.
  • In on_drag_data_received parse URIs via
    gtk_selection_data_get_uris() and convert them to file paths. Build
    newline‑separated text as the old Dart code expects.
  • Add defensive code for the rare case no data is available.
  • Update example app’s printFiles to ignore invalid (non‑absolute)
    paths and catch exceptions, making it safe to print debugging output.
  • Added an “Unreleased” entry in CHANGELOG.md describing the fix.

Testing

Recompiled the example on UOS and verified:

  1. dragging files now yields correct absolute paths,
  2. no PathNotFoundException is raised,
  3. example skips any stray invalid strings.

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-list by 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.

Comment on lines +34 to +46
// 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);
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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);

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +54
// fallback to the raw data as before
auto *data = gtk_selection_data_get_data(sdata);
if (data) {
text = g_strdup((gchar *)data);
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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);

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +27
// 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.
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants