1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:57:44 +00:00

WindowServer+LibGUI: Add ability to set per-window icons.

The icons are passed around as filesystem paths for now, since the shared
memory bitmaps only support 2 sides.
This commit is contained in:
Andreas Kling 2019-04-13 16:59:55 +02:00
parent 7a74b76769
commit c09c114d77
19 changed files with 151 additions and 16 deletions

View file

@ -45,10 +45,10 @@ void GButton::paint_event(GPaintEvent& event)
auto content_rect = rect().shrunken(10, 2);
auto icon_location = m_icon ? content_rect.center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2)) : Point();
if (m_being_pressed) {
content_rect.move_by(1, 1);
icon_location.move_by(1, 1);
}
if (m_icon && !m_caption.is_empty())
icon_location.set_x(content_rect.x());
if (m_being_pressed)
painter.translate(1, 1);
if (m_icon) {
if (is_enabled())
painter.blit(icon_location, *m_icon, m_icon->rect());
@ -56,6 +56,10 @@ void GButton::paint_event(GPaintEvent& event)
painter.blit_dimmed(icon_location, *m_icon, m_icon->rect());
}
auto& font = (m_checkable && m_checked) ? Font::default_bold_font() : this->font();
if (m_icon && !m_caption.is_empty()) {
content_rect.move_by(m_icon->width() + 4, 0);
content_rect.set_width(content_rect.width() - m_icon->width() - 4);
}
painter.draw_text(content_rect, m_caption, font, text_alignment(), foreground_color(), TextElision::Right);
}
@ -130,3 +134,11 @@ void GButton::set_action(GAction& action)
action.register_button({ }, *this);
set_enabled(action.is_enabled());
}
void GButton::set_icon(RetainPtr<GraphicsBitmap>&& icon)
{
if (m_icon.ptr() == icon.ptr())
return;
m_icon = move(icon);
update();
}

View file

@ -17,7 +17,7 @@ public:
String caption() const { return m_caption; }
void set_caption(const String&);
void set_icon(RetainPtr<GraphicsBitmap>&& icon) { m_icon = move(icon); }
void set_icon(RetainPtr<GraphicsBitmap>&&);
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
GraphicsBitmap* icon() { return m_icon.ptr(); }

View file

@ -69,12 +69,13 @@ public:
class GWMWindowStateChangedEvent : public GWMEvent {
public:
GWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active, GWindowType window_type, bool is_minimized)
GWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active, GWindowType window_type, bool is_minimized, const String& icon_path)
: GWMEvent(GEvent::Type::WM_WindowStateChanged, client_id, window_id)
, m_title(title)
, m_icon_path(icon_path)
, m_rect(rect)
, m_active(is_active)
, m_window_type(window_type)
, m_active(is_active)
, m_minimized(is_minimized)
{
}
@ -84,12 +85,14 @@ public:
bool is_active() const { return m_active; }
GWindowType window_type() const { return m_window_type; }
bool is_minimized() const { return m_minimized; }
String icon_path() const { return m_icon_path; }
private:
String m_title;
String m_icon_path;
Rect m_rect;
bool m_active;
GWindowType m_window_type;
bool m_active;
bool m_minimized;
};

View file

@ -174,7 +174,7 @@ void GEventLoop::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& wind
dbgprintf("GEventLoop: handle_wm_event: %d\n", (int)event.type);
#endif
if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged)
return post_event(window, make<GWMWindowStateChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active, (GWindowType)event.wm.window_type, event.wm.is_minimized));
return post_event(window, make<GWMWindowStateChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active, (GWindowType)event.wm.window_type, event.wm.is_minimized, String(event.wm.icon_path, event.wm.icon_path_length)));
if (event.type == WSAPI_ServerMessage::WM_WindowRemoved)
return post_event(window, make<GWMWindowRemovedEvent>(event.wm.client_id, event.wm.window_id));
ASSERT_NOT_REACHED();

View file

@ -448,3 +448,19 @@ void GWindow::set_modal(bool modal)
void GWindow::wm_event(GWMEvent&)
{
}
void GWindow::set_icon_path(const String& path)
{
if (m_icon_path == path)
return;
m_icon_path = path;
if (!m_window_id)
return;
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::SetWindowIcon;
message.window_id = m_window_id;
ASSERT(path.length() < sizeof(message.text));
strcpy(message.text, path.characters());
message.text_length = path.length();
GEventLoop::post_message_to_server(message);
}

View file

@ -100,6 +100,9 @@ public:
void set_override_cursor(GStandardCursor);
String icon_path() const { return m_icon_path; }
void set_icon_path(const String&);
virtual const char* class_name() const override { return "GWindow"; }
protected:
@ -123,6 +126,7 @@ private:
WeakPtr<GWidget> m_hovered_widget;
Rect m_rect_when_windowless;
String m_title_when_windowless;
String m_icon_path;
Vector<Rect> m_pending_paint_event_rects;
Size m_size_increment;
Size m_base_size;