diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index 2affc3c42d..2e3413333f 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -575,10 +576,10 @@ int main(int argc, char** argv) directory_view->on_drop = [&](const GUI::AbstractView&, const GUI::ModelIndex& index, const GUI::DropEvent& event) { if (!index.is_valid()) return; - if (event.data_type() != "url-list") + if (!event.mime_data().has_urls()) return; - auto paths_to_copy = event.data().split('\n'); - if (paths_to_copy.is_empty()) { + auto urls = event.mime_data().urls(); + if (urls.is_empty()) { dbg() << "No files to drop"; return; } @@ -587,8 +588,7 @@ int main(int argc, char** argv) if (!target_node.is_directory()) return; - for (auto& path_to_copy : paths_to_copy) { - auto url_to_copy = URL(path_to_copy); + for (auto& url_to_copy : urls) { if (!url_to_copy.is_valid()) continue; auto new_path = String::format("%s/%s", @@ -597,7 +597,7 @@ int main(int argc, char** argv) if (!FileUtils::copy_file_or_directory(url_to_copy.path(), new_path)) { auto error_message = String::format("Could not copy %s into %s.", - path_to_copy.characters(), + url_to_copy.to_string().characters(), new_path.characters()); GUI::MessageBox::show(error_message, "File Manager", GUI::MessageBox::Type::Error); } else { diff --git a/Applications/QuickShow/QSWidget.cpp b/Applications/QuickShow/QSWidget.cpp index 96d85c06ef..aebaa246f0 100644 --- a/Applications/QuickShow/QSWidget.cpp +++ b/Applications/QuickShow/QSWidget.cpp @@ -26,10 +26,11 @@ #include "QSWidget.h" #include -#include +#include #include #include #include +#include QSWidget::QSWidget(GUI::Widget* parent) : GUI::Frame(parent) @@ -130,15 +131,15 @@ void QSWidget::drop_event(GUI::DropEvent& event) event.accept(); window()->move_to_front(); - if (event.data_type() == "url-list") { - auto lines = event.data().split_view('\n'); - if (lines.is_empty()) + if (event.mime_data().has_urls()) { + auto urls = event.mime_data().urls(); + if (urls.is_empty()) return; - if (lines.size() > 1) { + if (urls.size() > 1) { GUI::MessageBox::show("QuickShow can only open one file at a time!", "One at a time please!", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window()); return; } - URL url(lines[0]); + auto url = urls.first(); auto bitmap = Gfx::Bitmap::load_from_file(url.path()); if (!bitmap) { GUI::MessageBox::show(String::format("Failed to open %s", url.to_string().characters()), "Cannot open image", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window()); diff --git a/Applications/TextEditor/TextEditorWidget.cpp b/Applications/TextEditor/TextEditorWidget.cpp index 4354167207..4bfba22bab 100644 --- a/Applications/TextEditor/TextEditorWidget.cpp +++ b/Applications/TextEditor/TextEditorWidget.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -191,12 +192,11 @@ TextEditorWidget::TextEditorWidget() if (needle.is_empty()) return; - auto found_range = m_editor->document().find_next(needle); - while(found_range.is_valid()) { - m_editor->set_selection(found_range); - m_editor->insert_at_cursor_or_replace_selection(substitute); - found_range = m_editor->document().find_next(needle); + while (found_range.is_valid()) { + m_editor->set_selection(found_range); + m_editor->insert_at_cursor_or_replace_selection(substitute); + found_range = m_editor->document().find_next(needle); } }); @@ -463,15 +463,14 @@ void TextEditorWidget::drop_event(GUI::DropEvent& event) event.accept(); window()->move_to_front(); - if (event.data_type() == "url-list") { - auto lines = event.data().split_view('\n'); - if (lines.is_empty()) + if (event.mime_data().has_urls()) { + auto urls = event.mime_data().urls(); + if (urls.is_empty() ) return; - if (lines.size() > 1) { + if (urls.size() > 1) { GUI::MessageBox::show("TextEditor can only open one file at a time!", "One at a time please!", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window()); return; } - URL url(lines[0]); - open_sesame(url.path()); + open_sesame(urls.first().path()); } } diff --git a/Libraries/LibGUI/Event.h b/Libraries/LibGUI/Event.h index c518a694a1..17e71783a0 100644 --- a/Libraries/LibGUI/Event.h +++ b/Libraries/LibGUI/Event.h @@ -32,6 +32,10 @@ #include #include +namespace Core { +class MimeData; +} + namespace GUI { class Event : public Core::Event { @@ -326,25 +330,18 @@ private: class DropEvent final : public Event { public: - DropEvent(const Gfx::Point& position, const String& text, const String& data_type, const String& data) - : Event(Event::Drop) - , m_position(position) - , m_text(text) - , m_data_type(data_type) - , m_data(data) - { - } + DropEvent(const Gfx::Point&, const String& text, NonnullRefPtr mime_data); + + ~DropEvent(); const Gfx::Point& position() const { return m_position; } const String& text() const { return m_text; } - const String& data_type() const { return m_data_type; } - const String& data() const { return m_data; } + const Core::MimeData& mime_data() const { return m_mime_data; } private: Gfx::Point m_position; String m_text; - String m_data_type; - String m_data; + NonnullRefPtr m_mime_data; }; } diff --git a/Libraries/LibGUI/FileSystemModel.cpp b/Libraries/LibGUI/FileSystemModel.cpp index ea7a12ffd9..b449a4aa48 100644 --- a/Libraries/LibGUI/FileSystemModel.cpp +++ b/Libraries/LibGUI/FileSystemModel.cpp @@ -561,7 +561,7 @@ bool FileSystemModel::accepts_drag(const ModelIndex& index, const StringView& da { if (!index.is_valid()) return false; - if (data_type != "url-list") + if (data_type != "text/uri-list") return false; auto& node = this->node(index); return node.is_directory(); diff --git a/Libraries/LibGUI/FileSystemModel.h b/Libraries/LibGUI/FileSystemModel.h index 83c9d39aed..98e7d61680 100644 --- a/Libraries/LibGUI/FileSystemModel.h +++ b/Libraries/LibGUI/FileSystemModel.h @@ -123,7 +123,7 @@ public: virtual void update() override; virtual ModelIndex parent_index(const ModelIndex&) const override; virtual ModelIndex index(int row, int column = 0, const ModelIndex& parent = ModelIndex()) const override; - virtual StringView drag_data_type() const override { return "url-list"; } + virtual StringView drag_data_type() const override { return "text/uri-list"; } virtual bool accepts_drag(const ModelIndex&, const StringView& data_type) override; static String timestamp_string(time_t timestamp) diff --git a/Libraries/LibGUI/Makefile b/Libraries/LibGUI/Makefile index 3ba8f92397..931cb40906 100644 --- a/Libraries/LibGUI/Makefile +++ b/Libraries/LibGUI/Makefile @@ -19,6 +19,7 @@ OBJS = \ Desktop.o \ Dialog.o \ DragOperation.o \ + Event.o \ FilePicker.o \ FileSystemModel.o \ FontDatabase.o \ diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index a0b5dc87c2..ca05ff9f17 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -188,7 +189,7 @@ void Window::event(Core::Event& event) if (!m_main_widget) return; auto result = m_main_widget->hit_test(drop_event.position()); - auto local_event = make(result.local_position, drop_event.text(), drop_event.data_type(), drop_event.data()); + auto local_event = make(result.local_position, drop_event.text(), drop_event.mime_data()); ASSERT(result.widget); return result.widget->dispatch_event(*local_event, this); } diff --git a/Libraries/LibGUI/WindowServerConnection.cpp b/Libraries/LibGUI/WindowServerConnection.cpp index bfcc000f2e..d1a17570e2 100644 --- a/Libraries/LibGUI/WindowServerConnection.cpp +++ b/Libraries/LibGUI/WindowServerConnection.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -309,8 +310,11 @@ void WindowServerConnection::handle(const Messages::WindowClient::AsyncSetWallpa void WindowServerConnection::handle(const Messages::WindowClient::DragDropped& message) { - if (auto* window = Window::from_window_id(message.window_id())) - Core::EventLoop::current().post_event(*window, make(message.mouse_position(), message.text(), message.data_type(), message.data())); + if (auto* window = Window::from_window_id(message.window_id())) { + auto mime_data = Core::MimeData::construct(); + mime_data->set_data(message.data_type(), message.data().to_byte_buffer()); + Core::EventLoop::current().post_event(*window, make(message.mouse_position(), message.text(), mime_data)); + } } void WindowServerConnection::handle(const Messages::WindowClient::DragAccepted&) diff --git a/Libraries/LibVT/TerminalWidget.cpp b/Libraries/LibVT/TerminalWidget.cpp index 4e6f9614cc..8cd6ea76d4 100644 --- a/Libraries/LibVT/TerminalWidget.cpp +++ b/Libraries/LibVT/TerminalWidget.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -698,21 +699,23 @@ void TerminalWidget::context_menu_event(GUI::ContextMenuEvent& event) void TerminalWidget::drop_event(GUI::DropEvent& event) { - if (event.data_type() == "text") { + if (event.mime_data().has_text()) { event.accept(); - write(m_ptm_fd, event.data().characters(), event.data().length()); - } else if (event.data_type() == "url-list") { + auto text = event.mime_data().text(); + write(m_ptm_fd, text.characters(), text.length()); + } else if (event.mime_data().has_urls()) { event.accept(); - auto lines = event.data().split('\n'); + auto urls = event.mime_data().urls(); bool first = true; - for (auto& line : lines) { - if (!first) + for (auto& url : event.mime_data().urls()) { + if (!first) { write(m_ptm_fd, " ", 1); - first = false; - - if (line.starts_with("file://")) - line = line.substring(7, line.length() - 7); - write(m_ptm_fd, line.characters(), line.length()); + first = false; + } + if (url.protocol() == "file") + write(m_ptm_fd, url.path().characters(), url.path().length()); + else + write(m_ptm_fd, url.to_string().characters(), url.to_string().length()); } } }