summaryrefslogtreecommitdiff
path: root/Libraries/LibGUI
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-11-07 23:14:21 +0330
committerAndreas Kling <kling@serenityos.org>2020-11-08 21:46:13 +0100
commit6d1e47e7dd1741aec64dd93a4d95ff1854e3abab (patch)
treed69b6ece9a552535db9d842e9b10b56928c505d5 /Libraries/LibGUI
parentc930e026240c2c255b77ad8b2322aeea9ab92ea3 (diff)
downloadserenity-6d1e47e7dd1741aec64dd93a4d95ff1854e3abab.zip
LibGUI+WindowServer: Make DragOperation hold a MimeData instance
...instead of maybe bitmap + a single mime type and its corresponding data. This allows drag&drop operations to hold multiple different kinds of data, and the views/applications to choose between those. For instance, Spreadsheet can keep the structure of the dragged cells, and still provide text-only data to be passed to different unrelated editors.
Diffstat (limited to 'Libraries/LibGUI')
-rw-r--r--Libraries/LibGUI/AbstractView.cpp28
-rw-r--r--Libraries/LibGUI/DragOperation.cpp34
-rw-r--r--Libraries/LibGUI/DragOperation.h16
-rw-r--r--Libraries/LibGUI/FileSystemModel.cpp2
-rw-r--r--Libraries/LibGUI/Model.cpp36
-rw-r--r--Libraries/LibGUI/Model.h3
-rw-r--r--Libraries/LibGUI/ModelRole.h2
-rw-r--r--Libraries/LibGUI/WindowServerConnection.cpp3
8 files changed, 79 insertions, 45 deletions
diff --git a/Libraries/LibGUI/AbstractView.cpp b/Libraries/LibGUI/AbstractView.cpp
index fe80611d61..4303e50513 100644
--- a/Libraries/LibGUI/AbstractView.cpp
+++ b/Libraries/LibGUI/AbstractView.cpp
@@ -291,33 +291,7 @@ void AbstractView::mousemove_event(MouseEvent& event)
dbg() << "Initiate drag!";
auto drag_operation = DragOperation::construct();
- RefPtr<Gfx::Bitmap> bitmap;
-
- StringBuilder text_builder;
- StringBuilder data_builder;
- bool first = true;
- m_selection.for_each_index([&](auto& index) {
- auto text_data = index.data();
- if (!first)
- text_builder.append(", ");
- text_builder.append(text_data.to_string());
-
- auto drag_data = index.data(ModelRole::DragData);
- data_builder.append(drag_data.to_string());
- data_builder.append('\n');
-
- first = false;
-
- if (!bitmap) {
- Variant icon_data = index.data(ModelRole::Icon);
- if (icon_data.is_icon())
- bitmap = icon_data.as_icon().bitmap_for_size(32);
- }
- });
-
- drag_operation->set_text(text_builder.to_string());
- drag_operation->set_bitmap(bitmap);
- drag_operation->set_data(data_type, data_builder.to_string());
+ drag_operation->set_mime_data(m_model->mime_data(m_selection));
auto outcome = drag_operation->exec();
diff --git a/Libraries/LibGUI/DragOperation.cpp b/Libraries/LibGUI/DragOperation.cpp
index f0355eaddb..d85e05fd80 100644
--- a/Libraries/LibGUI/DragOperation.cpp
+++ b/Libraries/LibGUI/DragOperation.cpp
@@ -27,6 +27,7 @@
#include <AK/Badge.h>
#include <AK/SharedBuffer.h>
#include <LibCore/EventLoop.h>
+#include <LibCore/MimeData.h>
#include <LibGUI/DragOperation.h>
#include <LibGUI/WindowServerConnection.h>
#include <LibGfx/Bitmap.h>
@@ -48,18 +49,25 @@ DragOperation::Outcome DragOperation::exec()
{
ASSERT(!s_current_drag_operation);
ASSERT(!m_event_loop);
+ ASSERT(m_mime_data);
int bitmap_id = -1;
Gfx::IntSize bitmap_size;
RefPtr<Gfx::Bitmap> shared_bitmap;
- if (m_bitmap) {
- shared_bitmap = m_bitmap->to_bitmap_backed_by_shared_buffer();
+ if (m_mime_data->has_format("image/x-raw-bitmap")) {
+ auto data = m_mime_data->data("image/x-raw-bitmap");
+ auto bitmap = Gfx::Bitmap::create_from_serialized_byte_buffer(move(data));
+ shared_bitmap = bitmap->to_bitmap_backed_by_shared_buffer();
shared_bitmap->shared_buffer()->share_with(WindowServerConnection::the().server_pid());
bitmap_id = shared_bitmap->shbuf_id();
bitmap_size = shared_bitmap->size();
}
- auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::StartDrag>(m_text, m_data_type, m_data, bitmap_id, bitmap_size);
+ auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::StartDrag>(
+ m_mime_data->text(),
+ m_mime_data->all_data(),
+ bitmap_id, bitmap_size);
+
if (!response->started()) {
m_outcome = Outcome::Cancelled;
return m_outcome;
@@ -94,4 +102,24 @@ void DragOperation::notify_cancelled(Badge<WindowServerConnection>)
s_current_drag_operation->done(Outcome::Cancelled);
}
+void DragOperation::set_text(const String& text)
+{
+ if (!m_mime_data)
+ m_mime_data = Core::MimeData::construct();
+ m_mime_data->set_text(text);
+}
+void DragOperation::set_bitmap(const Gfx::Bitmap* bitmap)
+{
+ if (!m_mime_data)
+ m_mime_data = Core::MimeData::construct();
+ if (bitmap)
+ m_mime_data->set_data("image/x-raw-bitmap", bitmap->serialize_to_byte_buffer());
+}
+void DragOperation::set_data(const String& data_type, const String& data)
+{
+ if (!m_mime_data)
+ m_mime_data = Core::MimeData::construct();
+ m_mime_data->set_data(data_type, data.to_byte_buffer());
+}
+
}
diff --git a/Libraries/LibGUI/DragOperation.h b/Libraries/LibGUI/DragOperation.h
index ffaf366598..8595c0a848 100644
--- a/Libraries/LibGUI/DragOperation.h
+++ b/Libraries/LibGUI/DragOperation.h
@@ -44,13 +44,10 @@ public:
virtual ~DragOperation() override;
- void set_text(const String& text) { m_text = text; }
- void set_bitmap(const Gfx::Bitmap* bitmap) { m_bitmap = bitmap; }
- void set_data(const String& data_type, const String& data)
- {
- m_data_type = data_type;
- m_data = data;
- }
+ void set_mime_data(RefPtr<Core::MimeData> mime_data) { m_mime_data = move(mime_data); }
+ void set_text(const String& text);
+ void set_bitmap(const Gfx::Bitmap* bitmap);
+ void set_data(const String& data_type, const String& data);
Outcome exec();
Outcome outcome() const { return m_outcome; }
@@ -66,10 +63,7 @@ private:
OwnPtr<Core::EventLoop> m_event_loop;
Outcome m_outcome { Outcome::None };
- String m_text;
- String m_data_type;
- String m_data;
- RefPtr<Gfx::Bitmap> m_bitmap;
+ RefPtr<Core::MimeData> m_mime_data;
};
}
diff --git a/Libraries/LibGUI/FileSystemModel.cpp b/Libraries/LibGUI/FileSystemModel.cpp
index dad8a513cc..b132e8800a 100644
--- a/Libraries/LibGUI/FileSystemModel.cpp
+++ b/Libraries/LibGUI/FileSystemModel.cpp
@@ -403,7 +403,7 @@ Variant FileSystemModel::data(const ModelIndex& index, ModelRole role) const
return node.full_path();
}
- if (role == ModelRole::DragData) {
+ if (role == ModelRole::MimeData) {
if (index.column() == Column::Name) {
StringBuilder builder;
builder.append("file://");
diff --git a/Libraries/LibGUI/Model.cpp b/Libraries/LibGUI/Model.cpp
index 838d347eb6..b9e9d1e30c 100644
--- a/Libraries/LibGUI/Model.cpp
+++ b/Libraries/LibGUI/Model.cpp
@@ -88,4 +88,40 @@ void Model::unregister_client(ModelClient& client)
m_clients.remove(&client);
}
+RefPtr<Core::MimeData> Model::mime_data(const ModelSelection& selection) const
+{
+ auto mime_data = Core::MimeData::construct();
+ RefPtr<Gfx::Bitmap> bitmap;
+
+ StringBuilder text_builder;
+ StringBuilder data_builder;
+ bool first = true;
+ selection.for_each_index([&](auto& index) {
+ auto text_data = index.data();
+ if (!first)
+ text_builder.append(", ");
+ text_builder.append(text_data.to_string());
+
+ if (!first)
+ data_builder.append('\n');
+ auto data = index.data(ModelRole::MimeData);
+ data_builder.append(data.to_string());
+
+ first = false;
+
+ if (!bitmap) {
+ Variant icon_data = index.data(ModelRole::Icon);
+ if (icon_data.is_icon())
+ bitmap = icon_data.as_icon().bitmap_for_size(32);
+ }
+ });
+
+ mime_data->set_data(drag_data_type(), data_builder.to_byte_buffer());
+ mime_data->set_text(text_builder.to_string());
+ if (bitmap)
+ mime_data->set_data("image/x-raw-bitmap", bitmap->serialize_to_byte_buffer());
+
+ return mime_data;
+}
+
}
diff --git a/Libraries/LibGUI/Model.h b/Libraries/LibGUI/Model.h
index ed73a16a66..de6defbb25 100644
--- a/Libraries/LibGUI/Model.h
+++ b/Libraries/LibGUI/Model.h
@@ -31,8 +31,10 @@
#include <AK/HashTable.h>
#include <AK/RefCounted.h>
#include <AK/String.h>
+#include <LibCore/MimeData.h>
#include <LibGUI/ModelIndex.h>
#include <LibGUI/ModelRole.h>
+#include <LibGUI/ModelSelection.h>
#include <LibGUI/Variant.h>
#include <LibGfx/Forward.h>
#include <LibGfx/TextAlignment.h>
@@ -93,6 +95,7 @@ public:
}
virtual StringView drag_data_type() const { return {}; }
+ virtual RefPtr<Core::MimeData> mime_data(const ModelSelection&) const;
void register_view(Badge<AbstractView>, AbstractView&);
void unregister_view(Badge<AbstractView>, AbstractView&);
diff --git a/Libraries/LibGUI/ModelRole.h b/Libraries/LibGUI/ModelRole.h
index 79b868076d..8978808481 100644
--- a/Libraries/LibGUI/ModelRole.h
+++ b/Libraries/LibGUI/ModelRole.h
@@ -35,7 +35,7 @@ enum class ModelRole {
BackgroundColor,
Icon,
Font,
- DragData,
+ MimeData,
TextAlignment,
Search,
Custom = 0x100, // Applications are free to use roles above this number as they please
diff --git a/Libraries/LibGUI/WindowServerConnection.cpp b/Libraries/LibGUI/WindowServerConnection.cpp
index 8f846e7a46..4a5eb28f2e 100644
--- a/Libraries/LibGUI/WindowServerConnection.cpp
+++ b/Libraries/LibGUI/WindowServerConnection.cpp
@@ -307,8 +307,7 @@ 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())) {
- auto mime_data = Core::MimeData::construct();
- mime_data->set_data(message.data_type(), message.data().to_byte_buffer());
+ auto mime_data = Core::MimeData::construct(message.mime_data());
Core::EventLoop::current().post_event(*window, make<DropEvent>(message.mouse_position(), message.text(), mime_data));
}
}