summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthankyouverycool <66646555+thankyouverycool@users.noreply.github.com>2020-07-29 16:22:05 -0400
committerAndreas Kling <kling@serenityos.org>2020-08-01 07:56:48 +0200
commitc815fa7f474b3b74f1f973c03325265aaa149eac (patch)
tree2387e7b3238e463e1e57fb450061a5bc58b2dc30
parent41aacdf8158ff23c0105dae3defd1ab57ac9f2f5 (diff)
downloadserenity-c815fa7f474b3b74f1f973c03325265aaa149eac.zip
Services: Convert WindowFrame button bitmaps to themable PNGs
Custom buttons can now be set using TitleButtonIcons under the Paths group in themes. WindowFrame recognizes window-close.png, window-minimize.png, window-maximize.png and window-restore.png filenames.
-rw-r--r--Services/WindowServer/Button.cpp15
-rw-r--r--Services/WindowServer/Button.h9
-rw-r--r--Services/WindowServer/WindowFrame.cpp142
-rw-r--r--Services/WindowServer/WindowFrame.h2
-rw-r--r--Services/WindowServer/WindowManager.cpp1
5 files changed, 76 insertions, 93 deletions
diff --git a/Services/WindowServer/Button.cpp b/Services/WindowServer/Button.cpp
index 5dd45093dd..e87e64a558 100644
--- a/Services/WindowServer/Button.cpp
+++ b/Services/WindowServer/Button.cpp
@@ -33,10 +33,9 @@
namespace WindowServer {
-Button::Button(WindowFrame& frame, NonnullRefPtr<Gfx::CharacterBitmap>&& bitmap, Function<void(Button&)>&& on_click_handler)
+Button::Button(WindowFrame& frame, Function<void(Button&)>&& on_click_handler)
: on_click(move(on_click_handler))
, m_frame(frame)
- , m_bitmap(move(bitmap))
{
}
@@ -50,11 +49,13 @@ void Button::paint(Gfx::Painter& painter)
Gfx::PainterStateSaver saver(painter);
painter.translate(relative_rect().location());
Gfx::StylePainter::paint_button(painter, rect(), palette, Gfx::ButtonStyle::Normal, m_pressed, m_hovered);
- auto x_location = rect().center();
- x_location.move_by(-(m_bitmap->width() / 2), -(m_bitmap->height() / 2));
- if (m_pressed)
- x_location.move_by(1, 1);
- painter.draw_bitmap(x_location, *m_bitmap, palette.button_text());
+
+ if (m_icon) {
+ auto icon_location = rect().center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2));
+ if (m_pressed)
+ painter.translate(1, 1);
+ painter.blit(icon_location, *m_icon, m_icon->rect());
+ }
}
void Button::on_mouse_event(const MouseEvent& event)
diff --git a/Services/WindowServer/Button.h b/Services/WindowServer/Button.h
index 0002e92f88..7a2d6b82e9 100644
--- a/Services/WindowServer/Button.h
+++ b/Services/WindowServer/Button.h
@@ -27,10 +27,9 @@
#pragma once
#include <AK/Function.h>
-#include <AK/NonnullRefPtr.h>
#include <AK/Weakable.h>
-#include <LibGfx/Rect.h>
#include <LibGfx/Forward.h>
+#include <LibGfx/Rect.h>
namespace WindowServer {
@@ -39,7 +38,7 @@ class WindowFrame;
class Button : public Weakable<Button> {
public:
- Button(WindowFrame&, NonnullRefPtr<Gfx::CharacterBitmap>&&, Function<void(Button&)>&& on_click_handler);
+ Button(WindowFrame&, Function<void(Button&)>&& on_click_handler);
~Button();
Gfx::IntRect relative_rect() const { return m_relative_rect; }
@@ -56,12 +55,12 @@ public:
bool is_visible() const { return m_visible; }
- void set_bitmap(const Gfx::CharacterBitmap& bitmap) { m_bitmap = bitmap; }
+ void set_icon(const Gfx::Bitmap& icon) { m_icon = icon; }
private:
WindowFrame& m_frame;
Gfx::IntRect m_relative_rect;
- NonnullRefPtr<Gfx::CharacterBitmap> m_bitmap;
+ RefPtr<Gfx::Bitmap> m_icon;
bool m_pressed { false };
bool m_visible { true };
bool m_hovered { false };
diff --git a/Services/WindowServer/WindowFrame.cpp b/Services/WindowServer/WindowFrame.cpp
index 88d34e2b1d..58efa91240 100644
--- a/Services/WindowServer/WindowFrame.cpp
+++ b/Services/WindowServer/WindowFrame.cpp
@@ -26,7 +26,6 @@
#include "ClientConnection.h"
#include <AK/Badge.h>
-#include <LibGfx/CharacterBitmap.h>
#include <LibGfx/Font.h>
#include <LibGfx/Painter.h>
#include <LibGfx/StylePainter.h>
@@ -39,91 +38,24 @@
namespace WindowServer {
-static const char* s_close_button_bitmap_data = {
- "## ##"
- "### ###"
- " ###### "
- " #### "
- " #### "
- " ###### "
- "### ###"
- "## ##"
- " "
-};
-
-static Gfx::CharacterBitmap* s_close_button_bitmap;
-static const int s_close_button_bitmap_width = 8;
-static const int s_close_button_bitmap_height = 9;
-
-static const char* s_minimize_button_bitmap_data = {
- " "
- " "
- " "
- " ###### "
- " #### "
- " ## "
- " "
- " "
- " "
-};
-
-static Gfx::CharacterBitmap* s_minimize_button_bitmap;
-static const int s_minimize_button_bitmap_width = 8;
-static const int s_minimize_button_bitmap_height = 9;
-
-static const char* s_maximize_button_bitmap_data = {
- " "
- " "
- " "
- " ## "
- " #### "
- " ###### "
- " "
- " "
- " "
-};
-
-static Gfx::CharacterBitmap* s_maximize_button_bitmap;
-static const int s_maximize_button_bitmap_width = 8;
-static const int s_maximize_button_bitmap_height = 9;
-
-static const char* s_unmaximize_button_bitmap_data = {
- " "
- " ## "
- " #### "
- " ###### "
- " "
- " ###### "
- " #### "
- " ## "
- " "
-};
-
-static Gfx::CharacterBitmap* s_unmaximize_button_bitmap;
-static const int s_unmaximize_button_bitmap_width = 8;
-static const int s_unmaximize_button_bitmap_height = 9;
+static Gfx::Bitmap* s_minimize_icon;
+static Gfx::Bitmap* s_maximize_icon;
+static Gfx::Bitmap* s_restore_icon;
+static Gfx::Bitmap* s_close_icon;
+
+static String s_last_title_button_icons_path;
WindowFrame::WindowFrame(Window& window)
: m_window(window)
{
- if (!s_close_button_bitmap)
- s_close_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_close_button_bitmap_data, s_close_button_bitmap_width, s_close_button_bitmap_height).leak_ref();
-
- if (!s_minimize_button_bitmap)
- s_minimize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_minimize_button_bitmap_data, s_minimize_button_bitmap_width, s_minimize_button_bitmap_height).leak_ref();
-
- if (!s_maximize_button_bitmap)
- s_maximize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_maximize_button_bitmap_data, s_maximize_button_bitmap_width, s_maximize_button_bitmap_height).leak_ref();
-
- if (!s_unmaximize_button_bitmap)
- s_unmaximize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_unmaximize_button_bitmap_data, s_unmaximize_button_bitmap_width, s_unmaximize_button_bitmap_height).leak_ref();
-
- m_buttons.append(make<Button>(*this, *s_close_button_bitmap, [this](auto&) {
+ auto button = make<Button>(*this, [this](auto&) {
m_window.request_close();
- }));
+ });
+ m_close_button = button.ptr();
+ m_buttons.append(move(button));
if (window.is_resizable()) {
- auto button = make<Button>(*this, *s_maximize_button_bitmap, [this](auto&) {
+ auto button = make<Button>(*this, [this](auto&) {
m_window.set_maximized(!m_window.is_maximized());
});
m_maximize_button = button.ptr();
@@ -131,22 +63,70 @@ WindowFrame::WindowFrame(Window& window)
}
if (window.is_minimizable()) {
- auto button = make<Button>(*this, *s_minimize_button_bitmap, [this](auto&) {
+ auto button = make<Button>(*this, [this](auto&) {
m_window.set_minimized(true);
});
m_minimize_button = button.ptr();
m_buttons.append(move(button));
}
+
+ set_button_icons();
}
WindowFrame::~WindowFrame()
{
}
+void WindowFrame::set_button_icons()
+{
+ if (m_window.is_frameless())
+ return;
+
+ String icons_path = WindowManager::the().palette().title_button_icons_path();
+
+ StringBuilder full_path;
+ if (!s_minimize_icon || s_last_title_button_icons_path != icons_path) {
+ full_path.append(icons_path);
+ full_path.append("window-minimize.png");
+ if (!(s_minimize_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
+ s_minimize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-minimize.png").leak_ref();
+ full_path.clear();
+ }
+ if (!s_maximize_icon || s_last_title_button_icons_path != icons_path) {
+ full_path.append(icons_path);
+ full_path.append("window-maximize.png");
+ if (!(s_maximize_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
+ s_maximize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-maximize.png").leak_ref();
+ full_path.clear();
+ }
+ if (!s_restore_icon || s_last_title_button_icons_path != icons_path) {
+ full_path.append(icons_path);
+ full_path.append("window-restore.png");
+ if (!(s_restore_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
+ s_restore_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-restore.png").leak_ref();
+ full_path.clear();
+ }
+ if (!s_close_icon || s_last_title_button_icons_path != icons_path) {
+ full_path.append(icons_path);
+ full_path.append("window-close.png");
+ if (!(s_close_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
+ s_close_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-close.png").leak_ref();
+ full_path.clear();
+ }
+
+ m_close_button->set_icon(*s_close_icon);
+ if (m_window.is_minimizable())
+ m_minimize_button->set_icon(*s_minimize_icon);
+ if (m_window.is_resizable())
+ m_maximize_button->set_icon(m_window.is_maximized() ? *s_restore_icon : *s_maximize_icon);
+
+ s_last_title_button_icons_path = icons_path;
+}
+
void WindowFrame::did_set_maximized(Badge<Window>, bool maximized)
{
ASSERT(m_maximize_button);
- m_maximize_button->set_bitmap(maximized ? *s_unmaximize_button_bitmap : *s_maximize_button_bitmap);
+ m_maximize_button->set_icon(maximized ? *s_restore_icon : *s_maximize_icon);
}
Gfx::IntRect WindowFrame::title_bar_rect() const
diff --git a/Services/WindowServer/WindowFrame.h b/Services/WindowServer/WindowFrame.h
index 48373ee7aa..b7c4b309d4 100644
--- a/Services/WindowServer/WindowFrame.h
+++ b/Services/WindowServer/WindowFrame.h
@@ -54,6 +54,7 @@ public:
void did_set_maximized(Badge<Window>, bool);
void layout_buttons();
+ void set_button_icons();
private:
void paint_notification_frame(Gfx::Painter&);
@@ -69,6 +70,7 @@ private:
Window& m_window;
NonnullOwnPtrVector<Button> m_buttons;
+ Button* m_close_button { nullptr };
Button* m_maximize_button { nullptr };
Button* m_minimize_button { nullptr };
};
diff --git a/Services/WindowServer/WindowManager.cpp b/Services/WindowServer/WindowManager.cpp
index 688f713a64..60e88cfc43 100644
--- a/Services/WindowServer/WindowManager.cpp
+++ b/Services/WindowServer/WindowManager.cpp
@@ -1392,6 +1392,7 @@ bool WindowManager::update_theme(String theme_path, String theme_name)
}
}
window.frame().layout_buttons();
+ window.frame().set_button_icons();
return IterationDecision::Continue;
});
MenuManager::the().did_change_theme();