mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibGfx+LibIPC: Add Gfx::ShareableBitmap, a bitmap for easy IPC usage
With this patch, it's now possible to pass a Gfx::ShareableBitmap in an IPC message. As long as the message itself is synchronous, the bitmap will be adopted by the receiving end, and disowned by the sender nicely without any accounting effort like we've had to do in the past. Use this in NotificationServer to allow sending arbitrary bitmaps as icons instead of paths-to-icons.
This commit is contained in:
parent
24a0354ce8
commit
7cfe712f4d
Notes:
sideshowbarker
2024-07-19 08:04:01 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/7cfe712f4d0
17 changed files with 115 additions and 17 deletions
|
@ -116,7 +116,7 @@ void IRCWindow::post_notification_if_needed(const String& name, const String& me
|
||||||
notification->set_title(name);
|
notification->set_title(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
notification->set_icon_path("/res/icons/32x32/app-irc-client.png");
|
notification->set_icon(Gfx::Bitmap::load_from_file("/res/icons/32x32/app-irc-client.png"));
|
||||||
notification->set_text(message);
|
notification->set_text(message);
|
||||||
notification->show();
|
notification->show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,7 @@ int main(int argc, char** argv)
|
||||||
dbg() << "#include <AK/OwnPtr.h>";
|
dbg() << "#include <AK/OwnPtr.h>";
|
||||||
dbg() << "#include <LibGfx/Color.h>";
|
dbg() << "#include <LibGfx/Color.h>";
|
||||||
dbg() << "#include <LibGfx/Rect.h>";
|
dbg() << "#include <LibGfx/Rect.h>";
|
||||||
|
dbg() << "#include <LibGfx/ShareableBitmap.h>";
|
||||||
dbg() << "#include <LibIPC/Decoder.h>";
|
dbg() << "#include <LibIPC/Decoder.h>";
|
||||||
dbg() << "#include <LibIPC/Encoder.h>";
|
dbg() << "#include <LibIPC/Encoder.h>";
|
||||||
dbg() << "#include <LibIPC/Endpoint.h>";
|
dbg() << "#include <LibIPC/Endpoint.h>";
|
||||||
|
@ -362,6 +363,10 @@ int main(int argc, char** argv)
|
||||||
dbg() << " stream << rect.width();";
|
dbg() << " stream << rect.width();";
|
||||||
dbg() << " stream << rect.height();";
|
dbg() << " stream << rect.height();";
|
||||||
dbg() << " }";
|
dbg() << " }";
|
||||||
|
} else if (parameter.type == "Gfx::ShareableBitmap") {
|
||||||
|
dbg() << " stream << m_" << parameter.name << ".shbuf_id();";
|
||||||
|
dbg() << " stream << m_" << parameter.name << ".width();";
|
||||||
|
dbg() << " stream << m_" << parameter.name << ".height();";
|
||||||
} else {
|
} else {
|
||||||
dbg() << " stream << m_" << parameter.name << ";";
|
dbg() << " stream << m_" << parameter.name << ";";
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ DragOperation::Outcome DragOperation::exec()
|
||||||
Gfx::Size bitmap_size;
|
Gfx::Size bitmap_size;
|
||||||
RefPtr<Gfx::Bitmap> shared_bitmap;
|
RefPtr<Gfx::Bitmap> shared_bitmap;
|
||||||
if (m_bitmap) {
|
if (m_bitmap) {
|
||||||
shared_bitmap = m_bitmap->to_shareable_bitmap();
|
shared_bitmap = m_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();
|
||||||
|
|
|
@ -35,7 +35,7 @@ Notification::~Notification()
|
||||||
void Notification::show()
|
void Notification::show()
|
||||||
{
|
{
|
||||||
auto connection = NotificationServerConnection::construct();
|
auto connection = NotificationServerConnection::construct();
|
||||||
connection->post_message(Messages::NotificationServer::ShowNotification(m_text, m_title, m_icon_path));
|
connection->send_sync<Messages::NotificationServer::ShowNotification>(m_text, m_title, m_icon ? m_icon->to_shareable_bitmap(connection->server_pid()) : Gfx::ShareableBitmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibCore/Object.h>
|
#include <LibCore/Object.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
@ -16,8 +17,8 @@ public:
|
||||||
const String& title() const { return m_title; }
|
const String& title() const { return m_title; }
|
||||||
void set_title(const String& title) { m_title = title; }
|
void set_title(const String& title) { m_title = title; }
|
||||||
|
|
||||||
const String& icon_path() const { return m_icon_path; }
|
const Gfx::Bitmap* icon() const { return m_icon; }
|
||||||
void set_icon_path(const String& icon_path) { m_icon_path = icon_path; }
|
void set_icon(const Gfx::Bitmap* icon) { m_icon = icon; }
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ private:
|
||||||
|
|
||||||
String m_title;
|
String m_title;
|
||||||
String m_text;
|
String m_text;
|
||||||
String m_icon_path;
|
RefPtr<Gfx::Bitmap> m_icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/PNGLoader.h>
|
#include <LibGfx/PNGLoader.h>
|
||||||
|
#include <LibGfx/ShareableBitmap.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -97,7 +98,7 @@ Bitmap::Bitmap(BitmapFormat format, NonnullRefPtr<SharedBuffer>&& shared_buffer,
|
||||||
ASSERT(format != BitmapFormat::Indexed8);
|
ASSERT(format != BitmapFormat::Indexed8);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Bitmap> Bitmap::to_shareable_bitmap() const
|
NonnullRefPtr<Bitmap> Bitmap::to_bitmap_backed_by_shared_buffer() const
|
||||||
{
|
{
|
||||||
if (m_shared_buffer)
|
if (m_shared_buffer)
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -164,4 +165,12 @@ int Bitmap::shbuf_id() const
|
||||||
return m_shared_buffer ? m_shared_buffer->shbuf_id() : -1;
|
return m_shared_buffer ? m_shared_buffer->shbuf_id() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareableBitmap Bitmap::to_shareable_bitmap(pid_t peer_pid) const
|
||||||
|
{
|
||||||
|
auto bitmap = to_bitmap_backed_by_shared_buffer();
|
||||||
|
if (peer_pid > 0)
|
||||||
|
bitmap->shared_buffer()->share_with(peer_pid);
|
||||||
|
return ShareableBitmap(*bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
@ -49,7 +50,9 @@ public:
|
||||||
static RefPtr<Bitmap> load_from_file(const StringView& path);
|
static RefPtr<Bitmap> load_from_file(const StringView& path);
|
||||||
static NonnullRefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const Size&);
|
static NonnullRefPtr<Bitmap> create_with_shared_buffer(BitmapFormat, NonnullRefPtr<SharedBuffer>&&, const Size&);
|
||||||
|
|
||||||
NonnullRefPtr<Bitmap> to_shareable_bitmap() const;
|
NonnullRefPtr<Bitmap> to_bitmap_backed_by_shared_buffer() const;
|
||||||
|
|
||||||
|
ShareableBitmap to_shareable_bitmap(pid_t peer_pid = -1) const;
|
||||||
|
|
||||||
~Bitmap();
|
~Bitmap();
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ class Palette;
|
||||||
class PaletteImpl;
|
class PaletteImpl;
|
||||||
class Point;
|
class Point;
|
||||||
class Rect;
|
class Rect;
|
||||||
|
class ShareableBitmap;
|
||||||
class Size;
|
class Size;
|
||||||
class StylePainter;
|
class StylePainter;
|
||||||
struct SystemTheme;
|
struct SystemTheme;
|
||||||
|
|
|
@ -12,6 +12,7 @@ OBJS = \
|
||||||
Palette.o \
|
Palette.o \
|
||||||
Point.o \
|
Point.o \
|
||||||
Rect.o \
|
Rect.o \
|
||||||
|
ShareableBitmap.o \
|
||||||
Size.o \
|
Size.o \
|
||||||
StylePainter.o \
|
StylePainter.o \
|
||||||
SystemTheme.o \
|
SystemTheme.o \
|
||||||
|
|
40
Libraries/LibGfx/ShareableBitmap.cpp
Normal file
40
Libraries/LibGfx/ShareableBitmap.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <AK/SharedBuffer.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
#include <LibGfx/ShareableBitmap.h>
|
||||||
|
#include <LibIPC/Decoder.h>
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
ShareableBitmap::ShareableBitmap(const Bitmap& bitmap)
|
||||||
|
: m_bitmap(bitmap.to_bitmap_backed_by_shared_buffer())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
bool decode(Decoder& decoder, Gfx::ShareableBitmap& shareable_bitmap)
|
||||||
|
{
|
||||||
|
i32 shbuf_id = 0;
|
||||||
|
Gfx::Size size;
|
||||||
|
if (!decoder.decode(shbuf_id))
|
||||||
|
return false;
|
||||||
|
if (!decoder.decode(size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (shbuf_id == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
dbg() << "Decoding a ShareableBitmap with shbuf_id=" << shbuf_id << ", size=" << size;
|
||||||
|
|
||||||
|
auto shared_buffer = SharedBuffer::create_from_shbuf_id(shbuf_id);
|
||||||
|
if (!shared_buffer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto bitmap = Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGBA32, shared_buffer.release_nonnull(), size);
|
||||||
|
shareable_bitmap = bitmap->to_shareable_bitmap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
Libraries/LibGfx/ShareableBitmap.h
Normal file
35
Libraries/LibGfx/ShareableBitmap.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/RefPtr.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
#include <LibGfx/Size.h>
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
class ShareableBitmap {
|
||||||
|
public:
|
||||||
|
ShareableBitmap() {}
|
||||||
|
explicit ShareableBitmap(const Gfx::Bitmap&);
|
||||||
|
|
||||||
|
bool is_valid() const { return m_bitmap; }
|
||||||
|
|
||||||
|
i32 shbuf_id() const { return m_bitmap ? m_bitmap->shbuf_id() : -1; }
|
||||||
|
|
||||||
|
const Bitmap* bitmap() const { return m_bitmap; }
|
||||||
|
Bitmap* bitmap() { return m_bitmap; }
|
||||||
|
|
||||||
|
Size size() const { return m_bitmap ? m_bitmap->size() : Size(); }
|
||||||
|
Rect rect() const { return m_bitmap ? m_bitmap->rect() : Rect(); }
|
||||||
|
|
||||||
|
int width() const { return size().width(); }
|
||||||
|
int height() const { return size().height(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<Bitmap> m_bitmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
bool decode(Decoder&, Gfx::ShareableBitmap&);
|
||||||
|
}
|
|
@ -53,10 +53,11 @@ OwnPtr<Messages::NotificationServer::GreetResponse> ClientConnection::handle(con
|
||||||
return make<Messages::NotificationServer::GreetResponse>(client_id());
|
return make<Messages::NotificationServer::GreetResponse>(client_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientConnection::handle(const Messages::NotificationServer::ShowNotification& message)
|
OwnPtr<Messages::NotificationServer::ShowNotificationResponse> ClientConnection::handle(const Messages::NotificationServer::ShowNotification& message)
|
||||||
{
|
{
|
||||||
auto window = NotificationWindow::construct(message.text(), message.title(), message.icon_path());
|
auto window = NotificationWindow::construct(message.text(), message.title(), message.icon());
|
||||||
window->show();
|
window->show();
|
||||||
|
return make<Messages::NotificationServer::ShowNotificationResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ private:
|
||||||
explicit ClientConnection(Core::LocalSocket&, int client_id);
|
explicit ClientConnection(Core::LocalSocket&, int client_id);
|
||||||
|
|
||||||
virtual OwnPtr<Messages::NotificationServer::GreetResponse> handle(const Messages::NotificationServer::Greet&) override;
|
virtual OwnPtr<Messages::NotificationServer::GreetResponse> handle(const Messages::NotificationServer::Greet&) override;
|
||||||
virtual void handle(const Messages::NotificationServer::ShowNotification&) override;
|
virtual OwnPtr<Messages::NotificationServer::ShowNotificationResponse> handle(const Messages::NotificationServer::ShowNotification&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@ endpoint NotificationServer = 95
|
||||||
// Basic protocol
|
// Basic protocol
|
||||||
Greet() => (i32 client_id)
|
Greet() => (i32 client_id)
|
||||||
|
|
||||||
ShowNotification(String text, String title, String icon_path) =|
|
ShowNotification(String text, String title, Gfx::ShareableBitmap icon) => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <LibGUI/Widget.h>
|
#include <LibGUI/Widget.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/Font.h>
|
#include <LibGfx/Font.h>
|
||||||
|
#include <LibGfx/ShareableBitmap.h>
|
||||||
|
|
||||||
namespace NotificationServer {
|
namespace NotificationServer {
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ void update_notification_window_locations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationWindow::NotificationWindow(const String& text, const String& title, const String& icon_path)
|
NotificationWindow::NotificationWindow(const String& text, const String& title, const Gfx::ShareableBitmap& icon)
|
||||||
{
|
{
|
||||||
s_windows.append(this);
|
s_windows.append(this);
|
||||||
|
|
||||||
|
@ -86,11 +87,11 @@ NotificationWindow::NotificationWindow(const String& text, const String& title,
|
||||||
widget.layout()->set_margins({ 8, 8, 8, 8 });
|
widget.layout()->set_margins({ 8, 8, 8, 8 });
|
||||||
widget.layout()->set_spacing(6);
|
widget.layout()->set_spacing(6);
|
||||||
|
|
||||||
if (auto icon = Gfx::Bitmap::load_from_file(icon_path)) {
|
if (icon.is_valid()) {
|
||||||
auto& icon_label = widget.add<GUI::Label>();
|
auto& icon_label = widget.add<GUI::Label>();
|
||||||
icon_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed);
|
icon_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed);
|
||||||
icon_label.set_preferred_size(32, 32);
|
icon_label.set_preferred_size(32, 32);
|
||||||
icon_label.set_icon(icon);
|
icon_label.set_icon(icon.bitmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& left_container = widget.add<GUI::Widget>();
|
auto& left_container = widget.add<GUI::Widget>();
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
void set_original_rect(Gfx::Rect original_rect) { m_original_rect = original_rect; };
|
void set_original_rect(Gfx::Rect original_rect) { m_original_rect = original_rect; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NotificationWindow(const String& text, const String& title, const String& icon_path);
|
NotificationWindow(const String& text, const String& title, const Gfx::ShareableBitmap&);
|
||||||
|
|
||||||
Gfx::Rect m_original_rect;
|
Gfx::Rect m_original_rect;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <LibCore/ArgsParser.h>
|
#include <LibCore/ArgsParser.h>
|
||||||
#include <LibGUI/Application.h>
|
#include <LibGUI/Application.h>
|
||||||
#include <LibGUI/Notification.h>
|
#include <LibGUI/Notification.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -45,7 +46,7 @@ int main(int argc, char** argv)
|
||||||
auto notification = GUI::Notification::construct();
|
auto notification = GUI::Notification::construct();
|
||||||
notification->set_text(message);
|
notification->set_text(message);
|
||||||
notification->set_title(title);
|
notification->set_title(title);
|
||||||
notification->set_icon_path(icon_path);
|
notification->set_icon(Gfx::Bitmap::load_from_file(icon_path));
|
||||||
notification->show();
|
notification->show();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue