mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
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.
This commit is contained in:
parent
c930e02624
commit
6d1e47e7dd
15 changed files with 98 additions and 59 deletions
|
@ -55,8 +55,14 @@ public:
|
||||||
Vector<URL> urls() const;
|
Vector<URL> urls() const;
|
||||||
void set_urls(const Vector<URL>&);
|
void set_urls(const Vector<URL>&);
|
||||||
|
|
||||||
|
const HashMap<String, ByteBuffer>& all_data() const { return m_data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MimeData() { }
|
MimeData() { }
|
||||||
|
explicit MimeData(const HashMap<String, ByteBuffer>& data)
|
||||||
|
: m_data(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
HashMap<String, ByteBuffer> m_data;
|
HashMap<String, ByteBuffer> m_data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -291,33 +291,7 @@ void AbstractView::mousemove_event(MouseEvent& event)
|
||||||
dbg() << "Initiate drag!";
|
dbg() << "Initiate drag!";
|
||||||
auto drag_operation = DragOperation::construct();
|
auto drag_operation = DragOperation::construct();
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> bitmap;
|
drag_operation->set_mime_data(m_model->mime_data(m_selection));
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
auto outcome = drag_operation->exec();
|
auto outcome = drag_operation->exec();
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <AK/SharedBuffer.h>
|
#include <AK/SharedBuffer.h>
|
||||||
#include <LibCore/EventLoop.h>
|
#include <LibCore/EventLoop.h>
|
||||||
|
#include <LibCore/MimeData.h>
|
||||||
#include <LibGUI/DragOperation.h>
|
#include <LibGUI/DragOperation.h>
|
||||||
#include <LibGUI/WindowServerConnection.h>
|
#include <LibGUI/WindowServerConnection.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
|
@ -48,18 +49,25 @@ DragOperation::Outcome DragOperation::exec()
|
||||||
{
|
{
|
||||||
ASSERT(!s_current_drag_operation);
|
ASSERT(!s_current_drag_operation);
|
||||||
ASSERT(!m_event_loop);
|
ASSERT(!m_event_loop);
|
||||||
|
ASSERT(m_mime_data);
|
||||||
|
|
||||||
int bitmap_id = -1;
|
int bitmap_id = -1;
|
||||||
Gfx::IntSize bitmap_size;
|
Gfx::IntSize bitmap_size;
|
||||||
RefPtr<Gfx::Bitmap> shared_bitmap;
|
RefPtr<Gfx::Bitmap> shared_bitmap;
|
||||||
if (m_bitmap) {
|
if (m_mime_data->has_format("image/x-raw-bitmap")) {
|
||||||
shared_bitmap = m_bitmap->to_bitmap_backed_by_shared_buffer();
|
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());
|
shared_bitmap->shared_buffer()->share_with(WindowServerConnection::the().server_pid());
|
||||||
bitmap_id = shared_bitmap->shbuf_id();
|
bitmap_id = shared_bitmap->shbuf_id();
|
||||||
bitmap_size = shared_bitmap->size();
|
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()) {
|
if (!response->started()) {
|
||||||
m_outcome = Outcome::Cancelled;
|
m_outcome = Outcome::Cancelled;
|
||||||
return m_outcome;
|
return m_outcome;
|
||||||
|
@ -94,4 +102,24 @@ void DragOperation::notify_cancelled(Badge<WindowServerConnection>)
|
||||||
s_current_drag_operation->done(Outcome::Cancelled);
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,10 @@ public:
|
||||||
|
|
||||||
virtual ~DragOperation() override;
|
virtual ~DragOperation() override;
|
||||||
|
|
||||||
void set_text(const String& text) { m_text = text; }
|
void set_mime_data(RefPtr<Core::MimeData> mime_data) { m_mime_data = move(mime_data); }
|
||||||
void set_bitmap(const Gfx::Bitmap* bitmap) { m_bitmap = bitmap; }
|
void set_text(const String& text);
|
||||||
void set_data(const String& data_type, const String& data)
|
void set_bitmap(const Gfx::Bitmap* bitmap);
|
||||||
{
|
void set_data(const String& data_type, const String& data);
|
||||||
m_data_type = data_type;
|
|
||||||
m_data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
Outcome exec();
|
Outcome exec();
|
||||||
Outcome outcome() const { return m_outcome; }
|
Outcome outcome() const { return m_outcome; }
|
||||||
|
@ -66,10 +63,7 @@ private:
|
||||||
|
|
||||||
OwnPtr<Core::EventLoop> m_event_loop;
|
OwnPtr<Core::EventLoop> m_event_loop;
|
||||||
Outcome m_outcome { Outcome::None };
|
Outcome m_outcome { Outcome::None };
|
||||||
String m_text;
|
RefPtr<Core::MimeData> m_mime_data;
|
||||||
String m_data_type;
|
|
||||||
String m_data;
|
|
||||||
RefPtr<Gfx::Bitmap> m_bitmap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,7 +403,7 @@ Variant FileSystemModel::data(const ModelIndex& index, ModelRole role) const
|
||||||
return node.full_path();
|
return node.full_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == ModelRole::DragData) {
|
if (role == ModelRole::MimeData) {
|
||||||
if (index.column() == Column::Name) {
|
if (index.column() == Column::Name) {
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
builder.append("file://");
|
builder.append("file://");
|
||||||
|
|
|
@ -88,4 +88,40 @@ void Model::unregister_client(ModelClient& client)
|
||||||
m_clients.remove(&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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,10 @@
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
#include <LibCore/MimeData.h>
|
||||||
#include <LibGUI/ModelIndex.h>
|
#include <LibGUI/ModelIndex.h>
|
||||||
#include <LibGUI/ModelRole.h>
|
#include <LibGUI/ModelRole.h>
|
||||||
|
#include <LibGUI/ModelSelection.h>
|
||||||
#include <LibGUI/Variant.h>
|
#include <LibGUI/Variant.h>
|
||||||
#include <LibGfx/Forward.h>
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibGfx/TextAlignment.h>
|
#include <LibGfx/TextAlignment.h>
|
||||||
|
@ -93,6 +95,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual StringView drag_data_type() const { return {}; }
|
virtual StringView drag_data_type() const { return {}; }
|
||||||
|
virtual RefPtr<Core::MimeData> mime_data(const ModelSelection&) const;
|
||||||
|
|
||||||
void register_view(Badge<AbstractView>, AbstractView&);
|
void register_view(Badge<AbstractView>, AbstractView&);
|
||||||
void unregister_view(Badge<AbstractView>, AbstractView&);
|
void unregister_view(Badge<AbstractView>, AbstractView&);
|
||||||
|
|
|
@ -35,7 +35,7 @@ enum class ModelRole {
|
||||||
BackgroundColor,
|
BackgroundColor,
|
||||||
Icon,
|
Icon,
|
||||||
Font,
|
Font,
|
||||||
DragData,
|
MimeData,
|
||||||
TextAlignment,
|
TextAlignment,
|
||||||
Search,
|
Search,
|
||||||
Custom = 0x100, // Applications are free to use roles above this number as they please
|
Custom = 0x100, // Applications are free to use roles above this number as they please
|
||||||
|
|
|
@ -307,8 +307,7 @@ void WindowServerConnection::handle(const Messages::WindowClient::AsyncSetWallpa
|
||||||
void WindowServerConnection::handle(const Messages::WindowClient::DragDropped& message)
|
void WindowServerConnection::handle(const Messages::WindowClient::DragDropped& message)
|
||||||
{
|
{
|
||||||
if (auto* window = Window::from_window_id(message.window_id())) {
|
if (auto* window = Window::from_window_id(message.window_id())) {
|
||||||
auto mime_data = Core::MimeData::construct();
|
auto mime_data = Core::MimeData::construct(message.mime_data());
|
||||||
mime_data->set_data(message.data_type(), message.data().to_byte_buffer());
|
|
||||||
Core::EventLoop::current().post_event(*window, make<DropEvent>(message.mouse_position(), message.text(), mime_data));
|
Core::EventLoop::current().post_event(*window, make<DropEvent>(message.mouse_position(), message.text(), mime_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -755,7 +755,7 @@ OwnPtr<Messages::WindowServer::StartDragResponse> ClientConnection::handle(const
|
||||||
bitmap = Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGBA32, *shared_buffer, message.bitmap_size());
|
bitmap = Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGBA32, *shared_buffer, message.bitmap_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
wm.start_dnd_drag(*this, message.text(), bitmap, message.data_type(), message.data());
|
wm.start_dnd_drag(*this, message.text(), bitmap, Core::MimeData::construct(message.mime_data()));
|
||||||
return make<Messages::WindowServer::StartDragResponse>(true);
|
return make<Messages::WindowServer::StartDragResponse>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <Kernel/API/KeyCode.h>
|
#include <Kernel/API/KeyCode.h>
|
||||||
#include <LibCore/Event.h>
|
#include <LibCore/Event.h>
|
||||||
|
#include <LibCore/MimeData.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
#include <WindowServer/Cursor.h>
|
#include <WindowServer/Cursor.h>
|
||||||
#include <WindowServer/WindowType.h>
|
#include <WindowServer/WindowType.h>
|
||||||
|
@ -128,7 +129,7 @@ public:
|
||||||
const String& drag_data_type() const { return m_drag_data_type; }
|
const String& drag_data_type() const { return m_drag_data_type; }
|
||||||
|
|
||||||
void set_drag(bool b) { m_drag = b; }
|
void set_drag(bool b) { m_drag = b; }
|
||||||
void set_drag_data_type(const String& drag_data_type) { m_drag_data_type = drag_data_type; }
|
void set_mime_data(const Core::MimeData& mime_data) { m_mime_data = mime_data; }
|
||||||
|
|
||||||
MouseEvent translated(const Gfx::IntPoint& delta) const { return MouseEvent((Type)type(), m_position.translated(delta), m_buttons, m_button, m_modifiers, m_wheel_delta); }
|
MouseEvent translated(const Gfx::IntPoint& delta) const { return MouseEvent((Type)type(), m_position.translated(delta), m_buttons, m_button, m_modifiers, m_wheel_delta); }
|
||||||
|
|
||||||
|
@ -140,6 +141,7 @@ private:
|
||||||
int m_wheel_delta { 0 };
|
int m_wheel_delta { 0 };
|
||||||
bool m_drag { false };
|
bool m_drag { false };
|
||||||
String m_drag_data_type;
|
String m_drag_data_type;
|
||||||
|
RefPtr<const Core::MimeData> m_mime_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResizeEvent final : public Event {
|
class ResizeEvent final : public Event {
|
||||||
|
|
|
@ -32,7 +32,7 @@ endpoint WindowClient = 4
|
||||||
DragAccepted() =|
|
DragAccepted() =|
|
||||||
DragCancelled() =|
|
DragCancelled() =|
|
||||||
|
|
||||||
DragDropped(i32 window_id, Gfx::IntPoint mouse_position, [UTF8] String text, String data_type, String data) =|
|
DragDropped(i32 window_id, Gfx::IntPoint mouse_position, [UTF8] String text, HashMap<String,ByteBuffer> mime_data) =|
|
||||||
|
|
||||||
UpdateSystemTheme(i32 system_theme_buffer_id) =|
|
UpdateSystemTheme(i32 system_theme_buffer_id) =|
|
||||||
|
|
||||||
|
|
|
@ -705,7 +705,7 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
auto translated_event = event.translated(-window.position());
|
auto translated_event = event.translated(-window.position());
|
||||||
translated_event.set_drag(true);
|
translated_event.set_drag(true);
|
||||||
translated_event.set_drag_data_type(m_dnd_data_type);
|
translated_event.set_mime_data(*m_dnd_mime_data);
|
||||||
deliver_mouse_event(window, translated_event);
|
deliver_mouse_event(window, translated_event);
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
});
|
});
|
||||||
|
@ -727,7 +727,7 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win
|
||||||
m_dnd_client->post_message(Messages::WindowClient::DragAccepted());
|
m_dnd_client->post_message(Messages::WindowClient::DragAccepted());
|
||||||
if (hovered_window->client()) {
|
if (hovered_window->client()) {
|
||||||
auto translated_event = event.translated(-hovered_window->position());
|
auto translated_event = event.translated(-hovered_window->position());
|
||||||
hovered_window->client()->post_message(Messages::WindowClient::DragDropped(hovered_window->window_id(), translated_event.position(), m_dnd_text, m_dnd_data_type, m_dnd_data));
|
hovered_window->client()->post_message(Messages::WindowClient::DragDropped(hovered_window->window_id(), translated_event.position(), m_dnd_text, m_dnd_mime_data->all_data()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_dnd_client->post_message(Messages::WindowClient::DragCancelled());
|
m_dnd_client->post_message(Messages::WindowClient::DragCancelled());
|
||||||
|
@ -1355,14 +1355,13 @@ Gfx::IntRect WindowManager::maximized_window_rect(const Window& window) const
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::start_dnd_drag(ClientConnection& client, const String& text, Gfx::Bitmap* bitmap, const String& data_type, const String& data)
|
void WindowManager::start_dnd_drag(ClientConnection& client, const String& text, Gfx::Bitmap* bitmap, const Core::MimeData& mime_data)
|
||||||
{
|
{
|
||||||
ASSERT(!m_dnd_client);
|
ASSERT(!m_dnd_client);
|
||||||
m_dnd_client = client.make_weak_ptr();
|
m_dnd_client = client.make_weak_ptr();
|
||||||
m_dnd_text = text;
|
m_dnd_text = text;
|
||||||
m_dnd_bitmap = bitmap;
|
m_dnd_bitmap = bitmap;
|
||||||
m_dnd_data_type = data_type;
|
m_dnd_mime_data = mime_data;
|
||||||
m_dnd_data = data;
|
|
||||||
Compositor::the().invalidate_cursor();
|
Compositor::the().invalidate_cursor();
|
||||||
m_active_input_tracking_window = nullptr;
|
m_active_input_tracking_window = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,12 +100,11 @@ public:
|
||||||
|
|
||||||
const ClientConnection* dnd_client() const { return m_dnd_client.ptr(); }
|
const ClientConnection* dnd_client() const { return m_dnd_client.ptr(); }
|
||||||
const String& dnd_text() const { return m_dnd_text; }
|
const String& dnd_text() const { return m_dnd_text; }
|
||||||
const String& dnd_data_type() const { return m_dnd_data_type; }
|
const Core::MimeData& dnd_mime_data() const { return *m_dnd_mime_data; }
|
||||||
const String& dnd_data() const { return m_dnd_data; }
|
|
||||||
const Gfx::Bitmap* dnd_bitmap() const { return m_dnd_bitmap; }
|
const Gfx::Bitmap* dnd_bitmap() const { return m_dnd_bitmap; }
|
||||||
Gfx::IntRect dnd_rect() const;
|
Gfx::IntRect dnd_rect() const;
|
||||||
|
|
||||||
void start_dnd_drag(ClientConnection&, const String& text, Gfx::Bitmap*, const String& data_type, const String& data);
|
void start_dnd_drag(ClientConnection&, const String& text, Gfx::Bitmap*, const Core::MimeData&);
|
||||||
void end_dnd_drag();
|
void end_dnd_drag();
|
||||||
|
|
||||||
Window* active_window() { return m_active_window.ptr(); }
|
Window* active_window() { return m_active_window.ptr(); }
|
||||||
|
@ -331,8 +330,7 @@ private:
|
||||||
|
|
||||||
WeakPtr<ClientConnection> m_dnd_client;
|
WeakPtr<ClientConnection> m_dnd_client;
|
||||||
String m_dnd_text;
|
String m_dnd_text;
|
||||||
String m_dnd_data_type;
|
RefPtr<Core::MimeData> m_dnd_mime_data;
|
||||||
String m_dnd_data;
|
|
||||||
RefPtr<Gfx::Bitmap> m_dnd_bitmap;
|
RefPtr<Gfx::Bitmap> m_dnd_bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ endpoint WindowServer = 2
|
||||||
SetWindowCursor(i32 window_id, i32 cursor_type) => ()
|
SetWindowCursor(i32 window_id, i32 cursor_type) => ()
|
||||||
SetWindowCustomCursor(i32 window_id, Gfx::ShareableBitmap cursor) => ()
|
SetWindowCustomCursor(i32 window_id, Gfx::ShareableBitmap cursor) => ()
|
||||||
|
|
||||||
StartDrag([UTF8] String text, String data_type, String data, i32 bitmap_id, Gfx::IntSize bitmap_size) => (bool started)
|
StartDrag([UTF8] String text, HashMap<String,ByteBuffer> mime_data, i32 bitmap_id, Gfx::IntSize bitmap_size) => (bool started)
|
||||||
|
|
||||||
SetSystemTheme(String theme_path, [UTF8] String theme_name) => (bool success)
|
SetSystemTheme(String theme_path, [UTF8] String theme_name) => (bool success)
|
||||||
GetSystemTheme() => ([UTF8] String theme_name)
|
GetSystemTheme() => ([UTF8] String theme_name)
|
||||||
|
|
Loading…
Add table
Reference in a new issue