From acc107a44feadcaec5ecfc6fded97fb1a3421132 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Fri, 15 May 2020 22:35:03 +0300 Subject: [PATCH] FileManager+LibGUI+Userland: Switch clipboard to MIME types We will now actually use MIME types for clipboard. The default type is now "text/plain" (instead of just "text"). This also fixes some issues in copy(1) and paste(1). --- Applications/FileManager/main.cpp | 33 +++++++++++++++++-------------- Libraries/LibGUI/Clipboard.h | 2 +- Userland/copy.cpp | 4 ++-- Userland/paste.cpp | 7 ++++++- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index 31a2f4720da..b6f55275847 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -420,9 +420,10 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio StringBuilder copy_text; for (auto& path : paths) { - copy_text.appendf("%s\n", path.characters()); + auto url = URL::create_with_file_protocol(path); + copy_text.appendf("%s\n", url.to_string().characters()); } - GUI::Clipboard::the().set_data(copy_text.build(), "file-list"); + GUI::Clipboard::the().set_data(copy_text.build(), "text/uri-list"); }, window); copy_action->set_enabled(false); @@ -462,7 +463,7 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio auto do_paste = [&](const GUI::Action& action) { auto data_and_type = GUI::Clipboard::the().data_and_type(); - if (data_and_type.type != "file-list") { + if (data_and_type.type != "text/uri-list") { dbg() << "Cannot paste clipboard type " << data_and_type.type; return; } @@ -478,16 +479,18 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio else target_directory = directory_view.path(); - for (auto& current_path : copied_lines) { - if (current_path.is_empty()) + for (auto& uri_as_string : copied_lines) { + if (uri_as_string.is_empty()) continue; + URL url = uri_as_string; + if (!url.is_valid() || url.protocol() != "file") { + dbg() << "Cannot paste URI " << uri_as_string; + continue; + } - auto new_path = String::format("%s/%s", - target_directory.characters(), - FileSystemPath(current_path).basename().characters()); - if (!FileUtils::copy_file_or_directory(current_path, new_path)) { - auto error_message = String::format("Could not paste %s.", - current_path.characters()); + auto new_path = String::format("%s/%s", target_directory.characters(), url.basename().characters()); + if (!FileUtils::copy_file_or_directory(url.path(), new_path)) { + auto error_message = String::format("Could not paste %s.", url.path().characters()); GUI::MessageBox::show(error_message, "File Manager", GUI::MessageBox::Type::Error); } else { refresh_tree_view(); @@ -609,7 +612,7 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio GUI::Clipboard::the().on_change = [&](const String& data_type) { auto current_location = directory_view.path(); - paste_action->set_enabled(data_type == "file-list" && access(current_location.characters(), W_OK) == 0); + paste_action->set_enabled(data_type == "text/uri-list" && access(current_location.characters(), W_OK) == 0); }; auto menubar = GUI::MenuBar::construct(); @@ -678,7 +681,7 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio auto can_write_in_path = access(new_path.characters(), W_OK) == 0; mkdir_action->set_enabled(can_write_in_path); - paste_action->set_enabled(can_write_in_path && GUI::Clipboard::the().type() == "file-list"); + paste_action->set_enabled(can_write_in_path && GUI::Clipboard::the().type() == "text/uri-list"); go_forward_action->set_enabled(directory_view.path_history_position() < directory_view.path_history_size() - 1); go_back_action->set_enabled(directory_view.path_history_position() > 0); open_parent_directory_action->set_enabled(new_path != "/"); @@ -758,7 +761,7 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio auto& node = directory_view.model().node(index); if (node.is_directory()) { - auto should_get_enabled = access(node.full_path(directory_view.model()).characters(), W_OK) == 0 && GUI::Clipboard::the().type() == "file-list"; + auto should_get_enabled = access(node.full_path(directory_view.model()).characters(), W_OK) == 0 && GUI::Clipboard::the().type() == "text/uri-list"; folder_specific_paste_action->set_enabled(should_get_enabled); directory_context_menu->popup(event.screen_position()); } else { @@ -823,7 +826,7 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio directory_view.open(initial_location); directory_view.set_focus(true); - paste_action->set_enabled(GUI::Clipboard::the().type() == "file-list" && access(initial_location.characters(), W_OK) == 0); + paste_action->set_enabled(GUI::Clipboard::the().type() == "text/uri-list" && access(initial_location.characters(), W_OK) == 0); window->show(); diff --git a/Libraries/LibGUI/Clipboard.h b/Libraries/LibGUI/Clipboard.h index e04e04c8f06..cab0a52a45e 100644 --- a/Libraries/LibGUI/Clipboard.h +++ b/Libraries/LibGUI/Clipboard.h @@ -38,7 +38,7 @@ public: String data() const { return data_and_type().data; } String type() const { return data_and_type().type; } - void set_data(const StringView&, const String& data_type = "text"); + void set_data(const StringView&, const String& data_type = "text/plain"); struct DataAndType { String data; diff --git a/Userland/copy.cpp b/Userland/copy.cpp index a14409029fc..1a086df5df4 100644 --- a/Userland/copy.cpp +++ b/Userland/copy.cpp @@ -36,12 +36,12 @@ struct Options { String data; - StringView type { "text" }; + StringView type; }; Options parse_options(int argc, char* argv[]) { - const char* type = nullptr; + const char* type = "text/plain"; Vector text; Core::ArgsParser args_parser; diff --git a/Userland/paste.cpp b/Userland/paste.cpp index 8c60168ec10..b5eb2ab5d2a 100644 --- a/Userland/paste.cpp +++ b/Userland/paste.cpp @@ -46,11 +46,16 @@ int main(int argc, char* argv[]) auto& clipboard = GUI::Clipboard::the(); auto data_and_type = clipboard.data_and_type(); + if (data_and_type.type.is_null()) { + fprintf(stderr, "Nothing copied\n"); + return 1; + } + if (!print_type) { printf("%s", data_and_type.data.characters()); // Append a newline to text contents, but // only if we're not asked not to do this. - if (data_and_type.type == "text" && !no_newline) + if (data_and_type.type == "text/plain" && !no_newline) putchar('\n'); } else { printf("%s\n", data_and_type.type.characters());