1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:47:45 +00:00

WindowServer+LibGUI: Pass window icons as shared buffers rather than paths.

Now that we support more than 2 clients per shared buffer, we can use them
for window icons. I didn't do that previously since it would have made the
Taskbar process unable to access the icons.

This opens up some nice possibilities for programmatically generated icons.
This commit is contained in:
Andreas Kling 2019-07-28 10:18:49 +02:00
parent 63619b9f7c
commit 841b2e5d13
21 changed files with 193 additions and 19 deletions

View file

@ -40,6 +40,7 @@ public:
WM_WindowStateChanged,
WM_WindowRectChanged,
WM_WindowIconChanged,
WM_WindowIconBitmapChanged,
__End_WM_Events,
};
@ -133,6 +134,23 @@ private:
String m_icon_path;
};
class GWMWindowIconBitmapChangedEvent : public GWMEvent {
public:
GWMWindowIconBitmapChangedEvent(int client_id, int window_id, int icon_buffer_id, const Size& icon_size)
: GWMEvent(GEvent::Type::WM_WindowIconBitmapChanged, client_id, window_id)
, m_icon_buffer_id(icon_buffer_id)
, m_icon_size(icon_size)
{
}
int icon_buffer_id() const { return m_icon_buffer_id; }
const Size& icon_size() const { return m_icon_size; }
private:
int m_icon_buffer_id;
Size m_icon_size;
};
class GMultiPaintEvent final : public GEvent {
public:
explicit GMultiPaintEvent(const Vector<Rect, 32>& rects, const Size& window_size)

View file

@ -194,6 +194,8 @@ void GWindowServerConnection::handle_wm_event(const WSAPI_ServerMessage& event,
CEventLoop::current().post_event(window, make<GWMWindowRectChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.rect));
else if (event.type == WSAPI_ServerMessage::WM_WindowIconChanged)
CEventLoop::current().post_event(window, make<GWMWindowIconChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length)));
else if (event.type == WSAPI_ServerMessage::WM_WindowIconBitmapChanged)
CEventLoop::current().post_event(window, make<GWMWindowIconBitmapChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.icon_buffer_id, event.wm.icon_size));
else if (event.type == WSAPI_ServerMessage::WM_WindowRemoved)
CEventLoop::current().post_event(window, make<GWMWindowRemovedEvent>(event.wm.client_id, event.wm.window_id));
else
@ -301,12 +303,9 @@ void GWindowServerConnection::postprocess_bundles(Vector<IncomingMessageBundle>&
}
handle_resize_event(event, *window);
break;
case WSAPI_ServerMessage::Type::WM_WindowRemoved:
case WSAPI_ServerMessage::Type::WM_WindowStateChanged:
case WSAPI_ServerMessage::Type::WM_WindowIconChanged:
handle_wm_event(event, *window);
break;
default:
if (event.type > WSAPI_ServerMessage::__Begin_WM_Events__ && event.type < WSAPI_ServerMessage::Type::__End_WM_Events__)
handle_wm_event(event, *window);
break;
}
}

View file

@ -1,5 +1,6 @@
#include <AK/HashMap.h>
#include <AK/StringBuilder.h>
#include <LibC/SharedBuffer.h>
#include <LibC/stdio.h>
#include <LibC/stdlib.h>
#include <LibC/unistd.h>
@ -593,7 +594,7 @@ void GWindow::flip(const Vector<Rect, 32>& dirty_rects)
painter.blit(dirty_rect.location(), *m_front_bitmap, dirty_rect);
}
NonnullRefPtr<GraphicsBitmap> GWindow::create_backing_bitmap(const Size& size)
NonnullRefPtr<GraphicsBitmap> GWindow::create_shared_bitmap(GraphicsBitmap::Format format, const Size& size)
{
ASSERT(GWindowServerConnection::the().server_pid());
ASSERT(!size.is_empty());
@ -602,10 +603,15 @@ NonnullRefPtr<GraphicsBitmap> GWindow::create_backing_bitmap(const Size& size)
auto shared_buffer = SharedBuffer::create_with_size(size_in_bytes);
ASSERT(shared_buffer);
shared_buffer->share_with(GWindowServerConnection::the().server_pid());
auto format = m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32;
return GraphicsBitmap::create_with_shared_buffer(format, *shared_buffer, size);
}
NonnullRefPtr<GraphicsBitmap> GWindow::create_backing_bitmap(const Size& size)
{
auto format = m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32;
return create_shared_bitmap(format, size);
}
void GWindow::set_modal(bool modal)
{
ASSERT(!m_window_id);
@ -616,6 +622,27 @@ void GWindow::wm_event(GWMEvent&)
{
}
void GWindow::set_icon(const GraphicsBitmap* icon)
{
if (m_icon == icon)
return;
if (!m_window_id)
return;
m_icon = create_shared_bitmap(GraphicsBitmap::Format::RGBA32, icon->size());
{
GPainter painter(*m_icon);
painter.blit({ 0, 0 }, *icon, icon->rect());
}
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::SetWindowIconBitmap;
message.window_id = m_window_id;
message.window.icon_buffer_id = m_icon->shared_buffer_id();
message.window.icon_size = icon->size();
GWindowServerConnection::the().post_message_to_server(message);
}
void GWindow::set_icon_path(const StringView& path)
{
if (m_icon_path == path)

View file

@ -122,6 +122,9 @@ public:
String icon_path() const { return m_icon_path; }
void set_icon_path(const StringView&);
void set_icon(const GraphicsBitmap*);
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
Vector<GWidget*> focusable_widgets() const;
protected:
@ -135,11 +138,13 @@ private:
void collect_keyboard_activation_targets();
NonnullRefPtr<GraphicsBitmap> create_backing_bitmap(const Size&);
NonnullRefPtr<GraphicsBitmap> create_shared_bitmap(GraphicsBitmap::Format, const Size&);
void set_current_backing_bitmap(GraphicsBitmap&, bool flush_immediately = false);
void flip(const Vector<Rect, 32>& dirty_rects);
RefPtr<GraphicsBitmap> m_front_bitmap;
RefPtr<GraphicsBitmap> m_back_bitmap;
RefPtr<GraphicsBitmap> m_icon;
int m_window_id { 0 };
float m_opacity_when_windowless { 1.0f };
GWidget* m_main_widget { nullptr };