Ver código fonte

LibGUI+LibDraw: Add "Palette" concept for scoped color theming

GApplication now has a palette. This palette contains all the system
theme colors by default, and is inherited by a new top-level GWidget.
New child widgets inherit their parents palette.

It is possible to override the GApplication palette, and the palette
of any GWidget.

The Palette object contains a bunch of colors, each corresponding to
a ColorRole. Each role has a convenience getter as well.

Each GWidget now has a background_role() and foreground_role(), which
are then looked up in their current palette when painting. This means
that you no longer alter the background color of a widget by setting
it directly, rather you alter either its background role, or the
widget's palette.
Andreas Kling 5 anos atrás
pai
commit
a79bac428b
62 arquivos alterados com 448 adições e 410 exclusões
  1. 2 1
      Applications/FontEditor/GlyphMapWidget.cpp
  2. 2 1
      Applications/HexEditor/HexEditor.cpp
  3. 0 1
      Applications/IRCClient/IRCAppWindow.cpp
  4. 0 1
      Applications/PaintBrush/PaletteWidget.cpp
  5. 0 1
      Applications/PaintBrush/ToolboxWidget.cpp
  6. 0 1
      Applications/SystemMonitor/NetworkStatisticsWidget.cpp
  7. 3 4
      Applications/SystemMonitor/main.cpp
  8. 1 4
      Applications/Terminal/main.cpp
  9. 3 3
      Applications/Welcome/TextWidget.cpp
  10. 2 2
      Demos/Fire/Fire.cpp
  11. 1 1
      DevTools/HackStudio/Editor.cpp
  12. 0 1
      DevTools/HackStudio/FormWidget.cpp
  13. 0 1
      DevTools/VisualBuilder/VBForm.cpp
  14. 0 1
      Games/Minesweeper/Field.cpp
  15. 0 88
      Libraries/LibDraw/Color.cpp
  16. 1 33
      Libraries/LibDraw/Color.h
  17. 1 0
      Libraries/LibDraw/Makefile
  18. 26 0
      Libraries/LibDraw/Palette.cpp
  19. 51 0
      Libraries/LibDraw/Palette.h
  20. 40 39
      Libraries/LibDraw/StylePainter.cpp
  21. 7 8
      Libraries/LibDraw/StylePainter.h
  22. 31 28
      Libraries/LibDraw/SystemTheme.cpp
  23. 36 36
      Libraries/LibDraw/SystemTheme.h
  24. 2 1
      Libraries/LibGUI/GAbstractButton.cpp
  25. 6 5
      Libraries/LibGUI/GAbstractColumnView.cpp
  26. 1 1
      Libraries/LibGUI/GAbstractColumnView.h
  27. 17 0
      Libraries/LibGUI/GApplication.cpp
  28. 10 0
      Libraries/LibGUI/GApplication.h
  29. 1 1
      Libraries/LibGUI/GButton.cpp
  30. 7 6
      Libraries/LibGUI/GCheckBox.cpp
  31. 0 1
      Libraries/LibGUI/GFilePicker.cpp
  32. 1 1
      Libraries/LibGUI/GFrame.cpp
  33. 5 6
      Libraries/LibGUI/GGroupBox.cpp
  34. 7 5
      Libraries/LibGUI/GItemView.cpp
  35. 4 3
      Libraries/LibGUI/GLabel.cpp
  36. 6 4
      Libraries/LibGUI/GListView.cpp
  37. 1 1
      Libraries/LibGUI/GProgressBar.cpp
  38. 4 2
      Libraries/LibGUI/GResizeCorner.cpp
  39. 7 6
      Libraries/LibGUI/GScrollBar.cpp
  40. 2 2
      Libraries/LibGUI/GSlider.cpp
  41. 4 3
      Libraries/LibGUI/GSplitter.cpp
  42. 1 1
      Libraries/LibGUI/GStatusBar.cpp
  43. 8 9
      Libraries/LibGUI/GTabWidget.cpp
  44. 14 11
      Libraries/LibGUI/GTableView.cpp
  45. 10 8
      Libraries/LibGUI/GTextEditor.cpp
  46. 5 4
      Libraries/LibGUI/GToolBar.cpp
  47. 9 7
      Libraries/LibGUI/GTreeView.cpp
  48. 16 12
      Libraries/LibGUI/GWidget.cpp
  49. 16 1
      Libraries/LibGUI/GWidget.h
  50. 2 0
      Libraries/LibGUI/GWindowServerConnection.cpp
  51. 2 2
      Libraries/LibHTML/HtmlView.cpp
  52. 1 1
      Libraries/LibHTML/Layout/LayoutImage.cpp
  53. 5 1
      Libraries/LibHTML/RenderingContext.h
  54. 3 2
      Servers/WindowServer/WSButton.cpp
  55. 1 1
      Servers/WindowServer/WSCompositor.cpp
  56. 14 13
      Servers/WindowServer/WSMenu.cpp
  57. 8 7
      Servers/WindowServer/WSMenuManager.cpp
  58. 15 14
      Servers/WindowServer/WSWindowFrame.cpp
  59. 3 1
      Servers/WindowServer/WSWindowManager.cpp
  60. 10 2
      Servers/WindowServer/WSWindowManager.h
  61. 10 9
      Servers/WindowServer/WSWindowSwitcher.cpp
  62. 3 1
      Servers/WindowServer/main.cpp

+ 2 - 1
Applications/FontEditor/GlyphMapWidget.cpp

@@ -1,4 +1,5 @@
 #include "GlyphMapWidget.h"
+#include <LibDraw/Palette.h>
 #include <LibGUI/GPainter.h>
 
 GlyphMapWidget::GlyphMapWidget(Font& mutable_font, GWidget* parent)
@@ -74,7 +75,7 @@ void GlyphMapWidget::paint_event(GPaintEvent& event)
                 font().max_glyph_width(),
                 font().glyph_height());
             if (glyph == m_selected_glyph) {
-                painter.fill_rect(outer_rect, SystemColor::Selection);
+                painter.fill_rect(outer_rect, palette().selection());
                 painter.draw_glyph(inner_rect.location(), glyph, Color::White);
             } else {
                 painter.draw_glyph(inner_rect.location(), glyph, Color::Black);

+ 2 - 1
Applications/HexEditor/HexEditor.cpp

@@ -1,6 +1,7 @@
 #include "HexEditor.h"
 #include <AK/StringBuilder.h>
 #include <Kernel/KeyCode.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GClipboard.h>
 #include <LibGUI/GFontDatabase.h>
@@ -492,7 +493,7 @@ void HexEditor::paint_event(GPaintEvent& event)
                 text_color = Color::Red;
             }
 
-            Color highlight_color = SystemColor::Selection;
+            Color highlight_color = palette().selection();
             auto highlight_flag = false;
             if (m_selection_start > -1 && m_selection_end > -1) {
                 if (byte_position >= m_selection_start && byte_position <= m_selection_end) {

+ 0 - 1
Applications/IRCClient/IRCAppWindow.cpp

@@ -156,7 +156,6 @@ void IRCAppWindow::setup_widgets()
     auto widget = GWidget::construct();
     set_main_widget(widget);
     widget->set_fill_with_background_color(true);
-    widget->set_background_color(SystemColor::Window);
     widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
     widget->layout()->set_spacing(0);
 

+ 0 - 1
Applications/PaintBrush/PaletteWidget.cpp

@@ -51,7 +51,6 @@ PaletteWidget::PaletteWidget(PaintableWidget& paintable_widget, GWidget* parent)
     set_frame_shadow(FrameShadow::Raised);
     set_frame_thickness(0);
     set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
 
     set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
     set_preferred_size(0, 34);

+ 0 - 1
Applications/PaintBrush/ToolboxWidget.cpp

@@ -35,7 +35,6 @@ private:
 ToolboxWidget::ToolboxWidget(GWidget* parent)
     : GFrame(parent)
 {
-    set_background_color(SystemColor::Window);
     set_fill_with_background_color(true);
 
     set_frame_thickness(1);

+ 0 - 1
Applications/SystemMonitor/NetworkStatisticsWidget.cpp

@@ -11,7 +11,6 @@ NetworkStatisticsWidget::NetworkStatisticsWidget(GWidget* parent)
         set_layout(make<GBoxLayout>(Orientation::Vertical));
         layout()->set_margins({ 4, 4, 4, 4 });
         set_fill_with_background_color(true);
-        set_background_color(SystemColor::Window);
 
         auto adapters_group_box = GGroupBox::construct("Adapters", this);
         adapters_group_box->set_layout(make<GBoxLayout>(Orientation::Vertical));

+ 3 - 4
Applications/SystemMonitor/main.cpp

@@ -53,7 +53,6 @@ int main(int argc, char** argv)
     auto keeper = GWidget::construct();
     keeper->set_layout(make<GBoxLayout>(Orientation::Vertical));
     keeper->set_fill_with_background_color(true);
-    keeper->set_background_color(SystemColor::Window);
     keeper->layout()->set_margins({ 4, 4, 4, 4 });
 
     auto tabwidget = GTabWidget::construct(keeper);
@@ -192,7 +191,7 @@ class ProgressBarPaintingDelegate final : public GTableCellPaintingDelegate {
 public:
     virtual ~ProgressBarPaintingDelegate() override {}
 
-    virtual void paint(GPainter& painter, const Rect& a_rect, const GModel& model, const GModelIndex& index) override
+    virtual void paint(GPainter& painter, const Rect& a_rect, const Palette& palette, const GModel& model, const GModelIndex& index) override
     {
         auto rect = a_rect.shrunken(2, 2);
         auto percentage = model.data(index, GModel::Role::Custom).to_int();
@@ -201,7 +200,7 @@ public:
         String text;
         if (data.is_string())
             text = data.as_string();
-        StylePainter::paint_progress_bar(painter, rect, 0, 100, percentage, text);
+        StylePainter::paint_progress_bar(painter, rect, palette, 0, 100, percentage, text);
         painter.draw_rect(rect, Color::Black);
     }
 };
@@ -355,7 +354,7 @@ NonnullRefPtr<GWidget> build_graphs_tab()
 
     graphs_container->on_first_show = [](auto& self) {
         self.set_fill_with_background_color(true);
-        self.set_background_color(SystemColor::Window);
+        self.set_background_role(ColorRole::Button);
         self.set_layout(make<GBoxLayout>(Orientation::Vertical));
         self.layout()->set_margins({ 4, 4, 4, 4 });
 

+ 1 - 4
Applications/Terminal/main.cpp

@@ -98,13 +98,13 @@ RefPtr<GWindow> create_settings_window(TerminalWidget& terminal, RefPtr<CConfigF
     auto settings = GWidget::construct();
     window->set_main_widget(settings);
     settings->set_fill_with_background_color(true);
+    settings->set_background_role(ColorRole::Button);
     settings->set_layout(make<GBoxLayout>(Orientation::Vertical));
     settings->layout()->set_margins({ 4, 4, 4, 4 });
 
     auto radio_container = GGroupBox::construct("Bell Mode", settings);
     radio_container->set_layout(make<GBoxLayout>(Orientation::Vertical));
     radio_container->layout()->set_margins({ 6, 16, 6, 6 });
-    radio_container->set_fill_with_background_color(true);
     radio_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
     radio_container->set_preferred_size(100, 70);
 
@@ -119,12 +119,9 @@ RefPtr<GWindow> create_settings_window(TerminalWidget& terminal, RefPtr<CConfigF
     auto slider_container = GGroupBox::construct("Background Opacity", settings);
     slider_container->set_layout(make<GBoxLayout>(Orientation::Vertical));
     slider_container->layout()->set_margins({ 6, 16, 6, 6 });
-    slider_container->set_fill_with_background_color(true);
     slider_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
     slider_container->set_preferred_size(100, 50);
     auto slider = GSlider::construct(Orientation::Horizontal, slider_container);
-    slider->set_fill_with_background_color(true);
-    slider->set_background_color(SystemColor::Window);
 
     slider->on_value_changed = [&terminal, &config](int value) {
         terminal.set_opacity(value);

+ 3 - 3
Applications/Welcome/TextWidget.cpp

@@ -1,10 +1,10 @@
+#include "TextWidget.h"
 #include <AK/String.h>
 #include <AK/StringBuilder.h>
 #include <AK/Vector.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GPainter.h>
 
-#include "TextWidget.h"
-
 TextWidget::TextWidget(GWidget* parent)
     : GFrame(parent)
 {
@@ -49,7 +49,7 @@ void TextWidget::paint_event(GPaintEvent& event)
             text_rect.set_width(text_rect.width() - indent * 2);
 
         if (is_enabled()) {
-            painter.draw_text(text_rect, line, m_text_alignment, foreground_color(), TextElision::None);
+            painter.draw_text(text_rect, line, m_text_alignment, palette().color(foreground_role()), TextElision::None);
         } else {
             painter.draw_text(text_rect.translated(1, 1), line, font(), text_alignment(), Color::White, TextElision::Right);
             painter.draw_text(text_rect, line, font(), text_alignment(), Color::from_rgb(0x808080), TextElision::Right);

+ 2 - 2
Demos/Fire/Fire.cpp

@@ -31,7 +31,7 @@
 #define FIRE_HEIGHT 168
 #define FIRE_MAX 29
 
-const Color palette[] = {
+static const Color s_palette[] = {
     Color(0x07, 0x07, 0x07), Color(0x1F, 0x07, 0x07), Color(0x2F, 0x0F, 0x07),
     Color(0x47, 0x0F, 0x07), Color(0x57, 0x17, 0x07), Color(0x67, 0x1F, 0x07),
     Color(0x77, 0x1F, 0x07), Color(0x9F, 0x2F, 0x07), Color(0xAF, 0x3F, 0x07),
@@ -93,7 +93,7 @@ Fire::Fire(GWidget* parent)
 
     /* Initialize fire palette */
     for (int i = 0; i < 30; i++)
-        bitmap->set_palette_color(i, palette[i]);
+        bitmap->set_palette_color(i, s_palette[i]);
 
     /* Set remaining entries to white */
     for (int i = 30; i < 256; i++)

+ 1 - 1
DevTools/HackStudio/Editor.cpp

@@ -68,7 +68,7 @@ void Editor::paint_event(GPaintEvent& event)
             rect.set_width(rect.width() - vertical_scrollbar().width());
         if (horizontal_scrollbar().is_visible())
             rect.set_height(rect.height() - horizontal_scrollbar().height());
-        painter.draw_rect(rect, SystemColor::Selection);
+        painter.draw_rect(rect, palette().selection());
     }
 }
 

+ 0 - 1
DevTools/HackStudio/FormWidget.cpp

@@ -7,7 +7,6 @@ FormWidget::FormWidget(FormEditorWidget& parent)
     : GWidget(&parent)
 {
     set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
     set_relative_rect(5, 5, 400, 300);
 
     set_greedy_for_hits(true);

+ 0 - 1
DevTools/VisualBuilder/VBForm.cpp

@@ -25,7 +25,6 @@ VBForm::VBForm(const String& name, GWidget* parent)
 {
     s_current = this;
     set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
     set_greedy_for_hits(true);
 
     m_context_menu = GMenu::construct();

+ 0 - 1
Games/Minesweeper/Field.cpp

@@ -121,7 +121,6 @@ Field::Field(GLabel& flag_label, GLabel& time_label, GButton& face_button, GWidg
         m_number_bitmap[i] = GraphicsBitmap::load_from_file(String::format("/res/icons/minesweeper/%u.png", i + 1));
 
     set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
     reset();
 
     m_face_button.on_click = [this](auto&) { reset(); };

+ 0 - 88
Libraries/LibDraw/Color.cpp

@@ -4,94 +4,6 @@
 #include <ctype.h>
 #include <stdio.h>
 
-Color::Color(SystemColor system_color)
-{
-    auto& theme = current_system_theme();
-    switch (system_color) {
-    case SystemColor::Window:
-        m_value = theme.window.value();
-        break;
-    case SystemColor::WindowText:
-        m_value = theme.window_text.value();
-        break;
-    case SystemColor::Base:
-        m_value = theme.base.value();
-        break;
-    case SystemColor::ThreedShadow1:
-        m_value = theme.threed_shadow1.value();
-        break;
-    case SystemColor::ThreedShadow2:
-        m_value = theme.threed_shadow2.value();
-        break;
-    case SystemColor::ThreedHighlight:
-        m_value = theme.threed_highlight.value();
-        break;
-    case SystemColor::Button:
-        m_value = theme.button.value();
-        break;
-    case SystemColor::ButtonText:
-        m_value = theme.button_text.value();
-        break;
-    case SystemColor::HoverHighlight:
-        m_value = theme.hover_highlight.value();
-        break;
-    case SystemColor::Selection:
-        m_value = theme.selection.value();
-        break;
-    case SystemColor::SelectionText:
-        m_value = theme.selection_text.value();
-        break;
-    case SystemColor::DesktopBackground:
-        m_value = theme.desktop_background.value();
-        break;
-    case SystemColor::ActiveWindowBorder1:
-        m_value = theme.active_window_border1.value();
-        break;
-    case SystemColor::ActiveWindowBorder2:
-        m_value = theme.active_window_border2.value();
-        break;
-    case SystemColor::ActiveWindowTitle:
-        m_value = theme.active_window_title.value();
-        break;
-    case SystemColor::InactiveWindowBorder1:
-        m_value = theme.inactive_window_border1.value();
-        break;
-    case SystemColor::InactiveWindowBorder2:
-        m_value = theme.inactive_window_border2.value();
-        break;
-    case SystemColor::InactiveWindowTitle:
-        m_value = theme.inactive_window_title.value();
-        break;
-    case SystemColor::MovingWindowBorder1:
-        m_value = theme.moving_window_border1.value();
-        break;
-    case SystemColor::MovingWindowBorder2:
-        m_value = theme.moving_window_border2.value();
-        break;
-    case SystemColor::MovingWindowTitle:
-        m_value = theme.moving_window_title.value();
-        break;
-    case SystemColor::HighlightWindowBorder1:
-        m_value = theme.highlight_window_border1.value();
-        break;
-    case SystemColor::HighlightWindowBorder2:
-        m_value = theme.highlight_window_border2.value();
-        break;
-    case SystemColor::HighlightWindowTitle:
-        m_value = theme.highlight_window_title.value();
-        break;
-    case SystemColor::MenuStripe:
-        m_value = theme.menu_stripe.value();
-        break;
-    case SystemColor::MenuBase:
-        m_value = theme.menu_base.value();
-        break;
-    case SystemColor::MenuSelection:
-        m_value = theme.menu_selection.value();
-        break;
-    }
-}
-
 Color::Color(NamedColor named)
 {
     struct {

+ 1 - 33
Libraries/LibDraw/Color.h

@@ -4,6 +4,7 @@
 #include <AK/String.h>
 #include <AK/Types.h>
 
+enum class ColorRole;
 typedef u32 RGBA32;
 
 inline constexpr u32 make_rgb(u8 r, u8 g, u8 b)
@@ -11,38 +12,6 @@ inline constexpr u32 make_rgb(u8 r, u8 g, u8 b)
     return ((r << 16) | (g << 8) | b);
 }
 
-enum class SystemColor {
-    DesktopBackground,
-    ActiveWindowBorder1,
-    ActiveWindowBorder2,
-    ActiveWindowTitle,
-    InactiveWindowBorder1,
-    InactiveWindowBorder2,
-    InactiveWindowTitle,
-    MovingWindowBorder1,
-    MovingWindowBorder2,
-    MovingWindowTitle,
-    HighlightWindowBorder1,
-    HighlightWindowBorder2,
-    HighlightWindowTitle,
-    MenuStripe,
-    MenuBase,
-    MenuSelection,
-    Window,
-    WindowText,
-    Button,
-    ButtonText,
-    Base,
-    ThreedHighlight,
-    ThreedShadow1,
-    ThreedShadow2,
-    HoverHighlight,
-    Selection,
-    SelectionText,
-
-    DisabledText = ThreedShadow1,
-};
-
 class Color {
 public:
     enum NamedColor {
@@ -71,7 +40,6 @@ public:
 
     Color() {}
     Color(NamedColor);
-    Color(SystemColor);
     Color(u8 r, u8 g, u8 b)
         : m_value(0xff000000 | (r << 16) | (g << 8) | b)
     {

+ 1 - 0
Libraries/LibDraw/Makefile

@@ -11,6 +11,7 @@ OBJS = \
     Rect.o \
     StylePainter.o \
     SystemTheme.o \
+    Palette.o \
     Emoji.o
 
 LIBRARY = libdraw.a

+ 26 - 0
Libraries/LibDraw/Palette.cpp

@@ -0,0 +1,26 @@
+#include <LibDraw/Palette.h>
+
+NonnullRefPtr<Palette> Palette::create_with_shared_buffer(SharedBuffer& buffer)
+{
+    return adopt(*new Palette(buffer));
+}
+
+Palette::Palette(SharedBuffer& buffer)
+    : m_theme_buffer(buffer)
+{
+}
+
+Palette::~Palette()
+{
+}
+
+const SystemTheme& Palette::theme() const
+{
+    return *(const SystemTheme*)m_theme_buffer->data();
+}
+
+Color Palette::color(ColorRole role) const
+{
+    ASSERT((int)role < (int)ColorRole::__Count);
+    return theme().color[(int)role];
+}

+ 51 - 0
Libraries/LibDraw/Palette.h

@@ -0,0 +1,51 @@
+#pragma once
+
+#include <AK/Badge.h>
+#include <LibDraw/SystemTheme.h>
+
+class GApplication;
+
+class Palette : public RefCounted<Palette> {
+public:
+    static NonnullRefPtr<Palette> create_with_shared_buffer(SharedBuffer&);
+    ~Palette();
+
+    Color window() const { return color(ColorRole::Window); }
+    Color window_text() const { return color(ColorRole::WindowText); }
+    Color selection() const { return color(ColorRole::Selection); }
+    Color selection_text() const { return color(ColorRole::SelectionText); }
+    Color desktop_background() const { return color(ColorRole::DesktopBackground); }
+    Color active_window_border1() const { return color(ColorRole::ActiveWindowBorder1); }
+    Color active_window_border2() const { return color(ColorRole::ActiveWindowBorder2); }
+    Color active_window_title() const { return color(ColorRole::ActiveWindowTitle); }
+    Color inactive_window_border1() const { return color(ColorRole::InactiveWindowBorder1); }
+    Color inactive_window_border2() const { return color(ColorRole::InactiveWindowBorder2); }
+    Color inactive_window_title() const { return color(ColorRole::InactiveWindowTitle); }
+    Color moving_window_border1() const { return color(ColorRole::MovingWindowBorder1); }
+    Color moving_window_border2() const { return color(ColorRole::MovingWindowBorder2); }
+    Color moving_window_title() const { return color(ColorRole::MovingWindowTitle); }
+    Color highlight_window_border1() const { return color(ColorRole::HighlightWindowBorder1); }
+    Color highlight_window_border2() const { return color(ColorRole::HighlightWindowBorder2); }
+    Color highlight_window_title() const { return color(ColorRole::HighlightWindowTitle); }
+    Color menu_stripe() const { return color(ColorRole::MenuStripe); }
+    Color menu_base() const { return color(ColorRole::MenuBase); }
+    Color menu_selection() const { return color(ColorRole::MenuSelection); }
+    Color base() const { return color(ColorRole::Base); }
+    Color button() const { return color(ColorRole::Button); }
+    Color button_text() const { return color(ColorRole::ButtonText); }
+    Color threed_highlight() const { return color(ColorRole::ThreedHighlight); }
+    Color threed_shadow1() const { return color(ColorRole::ThreedShadow1); }
+    Color threed_shadow2() const { return color(ColorRole::ThreedShadow2); }
+    Color hover_highlight() const { return color(ColorRole::ThreedHighlight); }
+
+    Color color(ColorRole) const;
+
+    const SystemTheme& theme() const;
+
+    void replace_internal_buffer(Badge<GApplication>, SharedBuffer& buffer) { m_theme_buffer = buffer; }
+
+private:
+    explicit Palette(SharedBuffer&);
+
+    RefPtr<SharedBuffer> m_theme_buffer;
+};

+ 40 - 39
Libraries/LibDraw/StylePainter.cpp

@@ -1,15 +1,16 @@
 #include <LibDraw/Painter.h>
+#include <LibDraw/Palette.h>
 #include <LibDraw/StylePainter.h>
 
-void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool active, bool hovered, bool enabled)
+void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, const Palette& palette, bool active, bool hovered, bool enabled)
 {
-    Color base_color = SystemColor::Button;
-    Color highlight_color2 = SystemColor::ThreedHighlight;
-    Color shadow_color1 = SystemColor::ThreedShadow1;
-    Color shadow_color2 = SystemColor::ThreedShadow2;
+    Color base_color = palette.button();
+    Color highlight_color2 = palette.threed_highlight();
+    Color shadow_color1 = palette.threed_shadow1();
+    Color shadow_color2 = palette.threed_shadow2();
 
     if (hovered && enabled && !active)
-        base_color = StylePainter::hover_highlight_color();
+        base_color = palette.hover_highlight();
 
     PainterStateSaver saver(painter);
     painter.translate(rect.location());
@@ -42,20 +43,20 @@ void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool act
         shadow_color2);
 }
 
-static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, bool checked, bool hovered, bool enabled)
+static void paint_button_new(Painter& painter, const Rect& rect, const Palette& palette, bool pressed, bool checked, bool hovered, bool enabled)
 {
-    Color button_color = SystemColor::Button;
-    Color highlight_color2 = SystemColor::ThreedHighlight;
-    Color shadow_color1 = SystemColor::ThreedShadow1;
-    Color shadow_color2 = SystemColor::ThreedShadow2;
+    Color button_color = palette.button();
+    Color highlight_color2 = palette.threed_highlight();
+    Color shadow_color1 = palette.threed_shadow1();
+    Color shadow_color2 = palette.threed_shadow2();
 
     if (checked && enabled) {
         if (hovered)
-            button_color = SystemColor::HoverHighlight;
+            button_color = palette.hover_highlight();
         else
-            button_color = SystemColor::Button;
+            button_color = palette.button();
     } else if (hovered && enabled)
-        button_color = StylePainter::hover_highlight_color();
+        button_color = palette.hover_highlight();
 
     PainterStateSaver saver(painter);
     painter.translate(rect.location());
@@ -87,14 +88,14 @@ static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, b
     }
 }
 
-void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled)
+void StylePainter::paint_button(Painter& painter, const Rect& rect, const Palette& palette, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled)
 {
     if (button_style == ButtonStyle::Normal)
-        return paint_button_new(painter, rect, pressed, checked, hovered, enabled);
+        return paint_button_new(painter, rect, palette, pressed, checked, hovered, enabled);
 
-    Color button_color = SystemColor::Button;
-    Color highlight_color = SystemColor::ThreedHighlight;
-    Color shadow_color = Color(96, 96, 96);
+    Color button_color = palette.button();
+    Color highlight_color = palette.threed_highlight();
+    Color shadow_color = palette.threed_shadow1();
 
     if (button_style == ButtonStyle::CoolBar && !enabled)
         return;
@@ -127,27 +128,27 @@ void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle
     }
 }
 
-void StylePainter::paint_surface(Painter& painter, const Rect& rect, bool paint_vertical_lines, bool paint_top_line)
+void StylePainter::paint_surface(Painter& painter, const Rect& rect, const Palette& palette, bool paint_vertical_lines, bool paint_top_line)
 {
-    painter.fill_rect({ rect.x(), rect.y() + 1, rect.width(), rect.height() - 2 }, SystemColor::Button);
-    painter.draw_line(rect.top_left(), rect.top_right(), paint_top_line ? SystemColor::ThreedHighlight : SystemColor::Button);
-    painter.draw_line(rect.bottom_left(), rect.bottom_right(), SystemColor::ThreedShadow1);
+    painter.fill_rect({ rect.x(), rect.y() + 1, rect.width(), rect.height() - 2 }, palette.button());
+    painter.draw_line(rect.top_left(), rect.top_right(), paint_top_line ? palette.threed_highlight() : palette.button());
+    painter.draw_line(rect.bottom_left(), rect.bottom_right(), palette.threed_shadow1());
     if (paint_vertical_lines) {
-        painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), SystemColor::ThreedHighlight);
-        painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), SystemColor::ThreedShadow1);
+        painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), palette.threed_highlight());
+        painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), palette.threed_shadow1());
     }
 }
 
-void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape shape, FrameShadow shadow, int thickness, bool skip_vertical_lines)
+void StylePainter::paint_frame(Painter& painter, const Rect& rect, const Palette& palette, FrameShape shape, FrameShadow shadow, int thickness, bool skip_vertical_lines)
 {
     Color top_left_color;
     Color bottom_right_color;
-    Color dark_shade = SystemColor::ThreedShadow1;
-    Color light_shade = SystemColor::ThreedHighlight;
+    Color dark_shade = palette.threed_shadow1();
+    Color light_shade = palette.threed_highlight();
 
     if (shape == FrameShape::Container && thickness >= 2) {
         if (shadow == FrameShadow::Raised) {
-            dark_shade = SystemColor::ThreedShadow2;
+            dark_shade = palette.threed_shadow2();
         }
     }
 
@@ -175,10 +176,10 @@ void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape sh
     if (shape == FrameShape::Container && thickness >= 2) {
         Color top_left_color;
         Color bottom_right_color;
-        Color dark_shade = SystemColor::ThreedShadow2;
-        Color light_shade = SystemColor::Button;
+        Color dark_shade = palette.threed_shadow2();
+        Color light_shade = palette.button();
         if (shadow == FrameShadow::Raised) {
-            dark_shade = SystemColor::ThreedShadow1;
+            dark_shade = palette.threed_shadow1();
             top_left_color = light_shade;
             bottom_right_color = dark_shade;
         } else if (shadow == FrameShadow::Sunken) {
@@ -205,12 +206,12 @@ void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape sh
     }
 }
 
-void StylePainter::paint_window_frame(Painter& painter, const Rect& rect)
+void StylePainter::paint_window_frame(Painter& painter, const Rect& rect, const Palette& palette)
 {
-    Color base_color = SystemColor::Button;
-    Color dark_shade = SystemColor::ThreedShadow2;
-    Color mid_shade = SystemColor::ThreedShadow1;
-    Color light_shade = SystemColor::ThreedHighlight;
+    Color base_color = palette.button();
+    Color dark_shade = palette.threed_shadow2();
+    Color mid_shade = palette.threed_shadow1();
+    Color light_shade = palette.threed_highlight();
 
     painter.draw_line(rect.top_left(), rect.top_right(), base_color);
     painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left(), base_color);
@@ -227,7 +228,7 @@ void StylePainter::paint_window_frame(Painter& painter, const Rect& rect)
     painter.draw_line(rect.bottom_left().translated(2, -2), rect.bottom_right().translated(-2, -2), base_color);
 }
 
-void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, int min, int max, int value, const StringView& text)
+void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, const Palette& palette, int min, int max, int value, const StringView& text)
 {
     // First we fill the entire widget with the gradient. This incurs a bit of
     // overdraw but ensures a consistent look throughout the progression.
@@ -249,7 +250,7 @@ void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, int mi
     Rect hole_rect { (int)progress_width, 0, (int)(rect.width() - progress_width), rect.height() };
     hole_rect.move_by(rect.location());
     PainterStateSaver saver(painter);
-    painter.fill_rect(hole_rect, Color::White);
+    painter.fill_rect(hole_rect, palette.base());
 
     painter.add_clip_rect(hole_rect);
     if (!text.is_null())

+ 7 - 8
Libraries/LibDraw/StylePainter.h

@@ -3,6 +3,7 @@
 #include <LibDraw/Color.h>
 
 class Painter;
+class Palette;
 class Rect;
 
 enum class ButtonStyle {
@@ -25,12 +26,10 @@ enum class FrameShape {
 
 class StylePainter {
 public:
-    static void paint_button(Painter&, const Rect&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true);
-    static void paint_tab_button(Painter&, const Rect&, bool active, bool hovered, bool enabled);
-    static void paint_surface(Painter&, const Rect&, bool paint_vertical_lines = true, bool paint_top_line = true);
-    static void paint_frame(Painter&, const Rect&, FrameShape, FrameShadow, int thickness, bool skip_vertical_lines = false);
-    static void paint_window_frame(Painter&, const Rect&);
-    static void paint_progress_bar(Painter&, const Rect&, int min, int max, int value, const StringView& text = {});
-
-    static Color hover_highlight_color() { return SystemColor::HoverHighlight; }
+    static void paint_button(Painter&, const Rect&, const Palette&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true);
+    static void paint_tab_button(Painter&, const Rect&, const Palette&, bool active, bool hovered, bool enabled);
+    static void paint_surface(Painter&, const Rect&, const Palette&, bool paint_vertical_lines = true, bool paint_top_line = true);
+    static void paint_frame(Painter&, const Rect&, const Palette&, FrameShape, FrameShadow, int thickness, bool skip_vertical_lines = false);
+    static void paint_window_frame(Painter&, const Rect&, const Palette&);
+    static void paint_progress_bar(Painter&, const Rect&, const Palette&, int min, int max, int value, const StringView& text = {});
 };

+ 31 - 28
Libraries/LibDraw/SystemTheme.cpp

@@ -41,34 +41,37 @@ RefPtr<SharedBuffer> load_system_theme(const String& path)
         return color.value();
     };
 
-    data->desktop_background = get("DesktopBackground");
-    data->threed_highlight = get("ThreedHighlight");
-    data->threed_shadow1 = get("ThreedShadow1");
-    data->threed_shadow2 = get("ThreedShadow2");
-    data->hover_highlight = get("HoverHighlight");
-    data->selection = get("Selection");
-    data->selection_text = get("SelectionText");
-    data->window = get("Window");
-    data->window_text = get("WindowText");
-    data->base = get("Base");
-    data->button = get("Button");
-    data->button_text = get("ButtonText");
-    data->desktop_background = get("DesktopBackground");
-    data->active_window_border1 = get("ActiveWindowBorder1");
-    data->active_window_border2 = get("ActiveWindowBorder2");
-    data->active_window_title = get("ActiveWindowTitle");
-    data->inactive_window_border1 = get("InactiveWindowBorder1");
-    data->inactive_window_border2 = get("InactiveWindowBorder2");
-    data->inactive_window_title = get("InactiveWindowTitle");
-    data->moving_window_border1 = get("MovingWindowBorder1");
-    data->moving_window_border2 = get("MovingWindowBorder2");
-    data->moving_window_title = get("MovingWindowTitle");
-    data->highlight_window_border1 = get("HighlightWindowBorder1");
-    data->highlight_window_border2 = get("HighlightWindowBorder2");
-    data->highlight_window_title = get("HighlightWindowTitle");
-    data->menu_stripe = get("MenuStripe");
-    data->menu_base = get("MenuBase");
-    data->menu_selection = get("MenuSelection");
+#define DO_COLOR(x) \
+    data->color[(int)ColorRole::x] = get(#x)
+
+    DO_COLOR(DesktopBackground);
+    DO_COLOR(ThreedHighlight);
+    DO_COLOR(ThreedShadow1);
+    DO_COLOR(ThreedShadow2);
+    DO_COLOR(HoverHighlight);
+    DO_COLOR(Selection);
+    DO_COLOR(SelectionText);
+    DO_COLOR(Window);
+    DO_COLOR(WindowText);
+    DO_COLOR(Base);
+    DO_COLOR(Button);
+    DO_COLOR(ButtonText);
+    DO_COLOR(DesktopBackground);
+    DO_COLOR(ActiveWindowBorder1);
+    DO_COLOR(ActiveWindowBorder2);
+    DO_COLOR(ActiveWindowTitle);
+    DO_COLOR(InactiveWindowBorder1);
+    DO_COLOR(InactiveWindowBorder2);
+    DO_COLOR(InactiveWindowTitle);
+    DO_COLOR(MovingWindowBorder1);
+    DO_COLOR(MovingWindowBorder2);
+    DO_COLOR(MovingWindowTitle);
+    DO_COLOR(HighlightWindowBorder1);
+    DO_COLOR(HighlightWindowBorder2);
+    DO_COLOR(HighlightWindowTitle);
+    DO_COLOR(MenuStripe);
+    DO_COLOR(MenuBase);
+    DO_COLOR(MenuSelection);
 
     buffer->seal();
     buffer->share_globally();

+ 36 - 36
Libraries/LibDraw/SystemTheme.h

@@ -4,43 +4,43 @@
 #include <LibC/SharedBuffer.h>
 #include <LibDraw/Color.h>
 
-struct SystemTheme {
-    Color desktop_background;
-
-    Color active_window_border1;
-    Color active_window_border2;
-    Color active_window_title;
-
-    Color inactive_window_border1;
-    Color inactive_window_border2;
-    Color inactive_window_title;
-
-    Color moving_window_border1;
-    Color moving_window_border2;
-    Color moving_window_title;
-
-    Color highlight_window_border1;
-    Color highlight_window_border2;
-    Color highlight_window_title;
-
-    Color menu_stripe;
-    Color menu_base;
-    Color menu_selection;
-
-    Color window;
-    Color window_text;
-    Color base;
-    Color button;
-    Color button_text;
-
-    Color threed_highlight;
-    Color threed_shadow1;
-    Color threed_shadow2;
-
-    Color hover_highlight;
+enum class ColorRole {
+    NoRole,
+    DesktopBackground,
+    ActiveWindowBorder1,
+    ActiveWindowBorder2,
+    ActiveWindowTitle,
+    InactiveWindowBorder1,
+    InactiveWindowBorder2,
+    InactiveWindowTitle,
+    MovingWindowBorder1,
+    MovingWindowBorder2,
+    MovingWindowTitle,
+    HighlightWindowBorder1,
+    HighlightWindowBorder2,
+    HighlightWindowTitle,
+    MenuStripe,
+    MenuBase,
+    MenuSelection,
+    Window,
+    WindowText,
+    Button,
+    ButtonText,
+    Base,
+    ThreedHighlight,
+    ThreedShadow1,
+    ThreedShadow2,
+    HoverHighlight,
+    Selection,
+    SelectionText,
+
+    __Count,
+
+    DisabledText = ThreedShadow1,
+};
 
-    Color selection;
-    Color selection_text;
+struct SystemTheme {
+    Color color[(int)ColorRole::__Count];
 };
 
 const SystemTheme& current_system_theme();

+ 2 - 1
Libraries/LibGUI/GAbstractButton.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAbstractButton.h>
 #include <LibGUI/GPainter.h>
 
@@ -154,7 +155,7 @@ void GAbstractButton::paint_text(GPainter& painter, const Rect& rect, const Font
 
     if (text().is_empty())
         return;
-    painter.draw_text(clipped_rect, text(), font, text_alignment, SystemColor::ButtonText, TextElision::Right);
+    painter.draw_text(clipped_rect, text(), font, text_alignment, palette().button_text(), TextElision::Right);
     if (is_focused())
         painter.draw_rect(clipped_rect.inflated(6, 4), Color(140, 140, 140));
 }

+ 6 - 5
Libraries/LibGUI/GAbstractColumnView.cpp

@@ -1,4 +1,5 @@
 #include <AK/StringBuilder.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAbstractColumnView.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GMenu.h>
@@ -99,9 +100,9 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
     if (!headers_visible())
         return;
     int exposed_width = max(content_size().width(), width());
-    painter.fill_rect({ 0, 0, exposed_width, header_height() }, SystemColor::Window);
-    painter.draw_line({ 0, 0 }, { exposed_width - 1, 0 }, SystemColor::ThreedHighlight);
-    painter.draw_line({ 0, header_height() - 1 }, { exposed_width - 1, header_height() - 1 }, SystemColor::ThreedShadow1);
+    painter.fill_rect({ 0, 0, exposed_width, header_height() }, palette().button());
+    painter.draw_line({ 0, 0 }, { exposed_width - 1, 0 }, palette().threed_highlight());
+    painter.draw_line({ 0, header_height() - 1 }, { exposed_width - 1, header_height() - 1 }, palette().threed_shadow1());
     int x_offset = 0;
     int column_count = model()->column_count();
     for (int column_index = 0; column_index < column_count; ++column_index) {
@@ -112,7 +113,7 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
         Rect cell_rect(x_offset, 0, column_width + horizontal_padding() * 2, header_height());
         bool pressed = column_index == m_pressed_column_header_index && m_pressed_column_header_is_pressed;
         bool hovered = column_index == m_hovered_column_header_index && model()->column_metadata(column_index).sortable == GModel::ColumnMetadata::Sortable::True;
-        StylePainter::paint_button(painter, cell_rect, ButtonStyle::Normal, pressed, hovered);
+        StylePainter::paint_button(painter, cell_rect, palette(), ButtonStyle::Normal, pressed, hovered);
         String text;
         if (is_key_column) {
             StringBuilder builder;
@@ -129,7 +130,7 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
         auto text_rect = cell_rect.translated(horizontal_padding(), 0);
         if (pressed)
             text_rect.move_by(1, 1);
-        painter.draw_text(text_rect, text, header_font(), TextAlignment::CenterLeft, SystemColor::ButtonText);
+        painter.draw_text(text_rect, text, header_font(), TextAlignment::CenterLeft, palette().button_text());
         x_offset += column_width + horizontal_padding() * 2;
     }
 }

+ 1 - 1
Libraries/LibGUI/GAbstractColumnView.h

@@ -9,7 +9,7 @@ class GTableCellPaintingDelegate {
 public:
     virtual ~GTableCellPaintingDelegate() {}
 
-    virtual void paint(GPainter&, const Rect&, const GModel&, const GModelIndex&) = 0;
+    virtual void paint(GPainter&, const Rect&, const Palette&, const GModel&, const GModelIndex&) = 0;
 };
 
 class GAbstractColumnView : public GAbstractView {

+ 17 - 0
Libraries/LibGUI/GApplication.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GApplication.h>
 #include <LibGUI/GDesktop.h>
@@ -142,3 +143,19 @@ void GApplication::did_delete_last_window(Badge<GWindow>)
     if (m_quit_when_last_window_deleted)
         m_event_loop->quit(0);
 }
+
+void GApplication::set_system_palette(SharedBuffer& buffer)
+{
+    if (!m_system_palette)
+        m_system_palette = Palette::create_with_shared_buffer(buffer);
+    else
+        m_system_palette->replace_internal_buffer({}, buffer);
+
+    if (!m_palette)
+        m_palette = m_system_palette;
+}
+
+void GApplication::set_palette(const Palette& palette)
+{
+    m_palette = palette;
+}

+ 10 - 0
Libraries/LibGUI/GApplication.h

@@ -10,7 +10,10 @@ class GAction;
 class GKeyEvent;
 class GMenuBar;
 class GWindow;
+class GWindowServerConnection;
+class Palette;
 class Point;
+class SharedBuffer;
 
 class GApplication {
 public:
@@ -39,9 +42,16 @@ public:
     const String& invoked_as() const { return m_invoked_as; }
     const Vector<String>& args() const { return m_args; }
 
+    const Palette& palette() const { return *m_palette; }
+    void set_palette(const Palette&);
+
+    void set_system_palette(SharedBuffer&);
+
 private:
     OwnPtr<CEventLoop> m_event_loop;
     OwnPtr<GMenuBar> m_menubar;
+    RefPtr<Palette> m_palette;
+    RefPtr<Palette> m_system_palette;
     HashMap<GShortcut, GAction*> m_global_shortcut_actions;
     class TooltipWindow;
     TooltipWindow* m_tooltip_window { nullptr };

+ 1 - 1
Libraries/LibGUI/GButton.cpp

@@ -27,7 +27,7 @@ void GButton::paint_event(GPaintEvent& event)
     GPainter painter(*this);
     painter.add_clip_rect(event.rect());
 
-    StylePainter::paint_button(painter, rect(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled());
+    StylePainter::paint_button(painter, rect(), palette(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled());
 
     if (text().is_empty() && !m_icon)
         return;

+ 7 - 6
Libraries/LibGUI/GCheckBox.cpp

@@ -1,8 +1,9 @@
 #include <Kernel/KeyCode.h>
-#include <LibGUI/GCheckBox.h>
-#include <LibGUI/GPainter.h>
 #include <LibDraw/CharacterBitmap.h>
+#include <LibDraw/Palette.h>
 #include <LibDraw/StylePainter.h>
+#include <LibGUI/GCheckBox.h>
+#include <LibGUI/GPainter.h>
 
 static const char* s_checked_bitmap_data = {
     "         "
@@ -48,14 +49,14 @@ void GCheckBox::paint_event(GPaintEvent& event)
     text_rect.set_height(font().glyph_height());
 
     if (fill_with_background_color())
-        painter.fill_rect(rect(), background_color());
+        painter.fill_rect(rect(), palette().window());
 
     Rect box_rect {
         0, height() / 2 - s_box_height / 2 - 1,
         s_box_width, s_box_height
     };
-    painter.fill_rect(box_rect, SystemColor::Base);
-    StylePainter::paint_frame(painter, box_rect, FrameShape::Container, FrameShadow::Sunken, 2);
+    painter.fill_rect(box_rect, palette().base());
+    StylePainter::paint_frame(painter, box_rect, palette(), FrameShape::Container, FrameShadow::Sunken, 2);
 
     if (is_being_pressed())
         painter.draw_rect(box_rect.shrunken(4, 4), Color::MidGray);
@@ -63,7 +64,7 @@ void GCheckBox::paint_event(GPaintEvent& event)
     if (is_checked()) {
         if (!s_checked_bitmap)
             s_checked_bitmap = &CharacterBitmap::create_from_ascii(s_checked_bitmap_data, s_checked_bitmap_width, s_checked_bitmap_height).leak_ref();
-        painter.draw_bitmap(box_rect.shrunken(4, 4).location(), *s_checked_bitmap, SystemColor::ButtonText);
+        painter.draw_bitmap(box_rect.shrunken(4, 4).location(), *s_checked_bitmap, palette().button_text());
     }
 
     paint_text(painter, text_rect, font(), TextAlignment::TopLeft);

+ 0 - 1
Libraries/LibGUI/GFilePicker.cpp

@@ -58,7 +58,6 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
     horizontal_container->set_layout(make<GBoxLayout>(Orientation::Horizontal));
     horizontal_container->layout()->set_margins({ 4, 4, 4, 4 });
     horizontal_container->set_fill_with_background_color(true);
-    horizontal_container->set_background_color(SystemColor::Window);
 
     auto vertical_container = GWidget::construct(horizontal_container.ptr());
     vertical_container->set_layout(make<GBoxLayout>(Orientation::Vertical));

+ 1 - 1
Libraries/LibGUI/GFrame.cpp

@@ -18,5 +18,5 @@ void GFrame::paint_event(GPaintEvent& event)
 
     GPainter painter(*this);
     painter.add_clip_rect(event.rect());
-    StylePainter::paint_frame(painter, rect(), m_shape, m_shadow, m_thickness, spans_entire_window_horizontally());
+    StylePainter::paint_frame(painter, rect(), palette(), m_shape, m_shadow, m_thickness, spans_entire_window_horizontally());
 }

+ 5 - 6
Libraries/LibGUI/GGroupBox.cpp

@@ -1,6 +1,7 @@
+#include <LibDraw/Palette.h>
+#include <LibDraw/StylePainter.h>
 #include <LibGUI/GGroupBox.h>
 #include <LibGUI/GPainter.h>
-#include <LibDraw/StylePainter.h>
 
 GGroupBox::GGroupBox(GWidget* parent)
     : GGroupBox({}, parent)
@@ -11,8 +12,6 @@ GGroupBox::GGroupBox(const StringView& title, GWidget* parent)
     : GWidget(parent)
     , m_title(title)
 {
-    set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
 }
 
 GGroupBox::~GGroupBox()
@@ -28,11 +27,11 @@ void GGroupBox::paint_event(GPaintEvent& event)
         0, font().glyph_height() / 2,
         width(), height() - font().glyph_height() / 2
     };
-    StylePainter::paint_frame(painter, frame_rect, FrameShape::Box, FrameShadow::Sunken, 2);
+    StylePainter::paint_frame(painter, frame_rect, palette(), FrameShape::Box, FrameShadow::Sunken, 2);
 
     Rect text_rect { 4, 0, font().width(m_title) + 6, font().glyph_height() };
-    painter.fill_rect(text_rect, background_color());
-    painter.draw_text(text_rect, m_title, TextAlignment::Center, foreground_color());
+    painter.fill_rect(text_rect, palette().button());
+    painter.draw_text(text_rect, m_title, TextAlignment::Center, palette().button_text());
 }
 
 void GGroupBox::set_title(const StringView& title)

+ 7 - 5
Libraries/LibGUI/GItemView.cpp

@@ -1,5 +1,6 @@
 #include <AK/StringBuilder.h>
 #include <Kernel/KeyCode.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GDragOperation.h>
 #include <LibGUI/GItemView.h>
 #include <LibGUI/GModel.h>
@@ -186,12 +187,13 @@ void GItemView::doubleclick_event(GMouseEvent& event)
 
 void GItemView::paint_event(GPaintEvent& event)
 {
+    Color widget_background_color = palette().color(background_role());
     GFrame::paint_event(event);
 
     GPainter painter(*this);
     painter.add_clip_rect(widget_inner_rect());
     painter.add_clip_rect(event.rect());
-    painter.fill_rect(event.rect(), SystemColor::Base);
+    painter.fill_rect(event.rect(), widget_background_color);
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
 
     auto column_metadata = model()->column_metadata(m_model_column);
@@ -201,9 +203,9 @@ void GItemView::paint_event(GPaintEvent& event)
         bool is_selected_item = selection().contains(model()->index(item_index, m_model_column));
         Color background_color;
         if (is_selected_item) {
-            background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
+            background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
         } else {
-            background_color = SystemColor::Base;
+            background_color = widget_background_color;
         }
 
         Rect item_rect = this->item_rect(item_index);
@@ -228,9 +230,9 @@ void GItemView::paint_event(GPaintEvent& event)
 
         Color text_color;
         if (is_selected_item)
-            text_color = SystemColor::SelectionText;
+            text_color = palette().selection_text();
         else
-            text_color = model()->data(model_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
+            text_color = model()->data(model_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
         painter.fill_rect(text_rect, background_color);
         painter.draw_text(text_rect, item_text.to_string(), font, TextAlignment::Center, text_color, TextElision::Right);
     };

+ 4 - 3
Libraries/LibGUI/GLabel.cpp

@@ -1,6 +1,7 @@
-#include "GLabel.h"
-#include <LibGUI/GPainter.h>
 #include <LibDraw/GraphicsBitmap.h>
+#include <LibDraw/Palette.h>
+#include <LibGUI/GLabel.h>
+#include <LibGUI/GPainter.h>
 
 GLabel::GLabel(GWidget* parent)
     : GFrame(parent)
@@ -58,7 +59,7 @@ void GLabel::paint_event(GPaintEvent& event)
     text_rect.set_width(text_rect.width() - indent * 2);
 
     if (is_enabled()) {
-        painter.draw_text(text_rect, text(), m_text_alignment, foreground_color(), TextElision::Right);
+        painter.draw_text(text_rect, text(), m_text_alignment, palette().window_text(), TextElision::Right);
     } else {
         painter.draw_text(text_rect.translated(1, 1), text(), font(), text_alignment(), Color::White, TextElision::Right);
         painter.draw_text(text_rect, text(), font(), text_alignment(), Color::from_rgb(0x808080), TextElision::Right);

+ 6 - 4
Libraries/LibGUI/GListView.cpp

@@ -1,4 +1,5 @@
 #include <Kernel/KeyCode.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GListView.h>
 #include <LibGUI/GPainter.h>
 #include <LibGUI/GScrollBar.h>
@@ -6,6 +7,7 @@
 GListView::GListView(GWidget* parent)
     : GAbstractView(parent)
 {
+    set_background_role(ColorRole::Base);
     set_frame_shape(FrameShape::Container);
     set_frame_shadow(FrameShadow::Sunken);
     set_frame_thickness(2);
@@ -104,12 +106,12 @@ void GListView::paint_event(GPaintEvent& event)
 
         Color background_color;
         if (is_selected_row) {
-            background_color = is_focused() ? Color(SystemColor::SelectionText) : Color::from_rgb(0x606060);
+            background_color = is_focused() ? palette().selection_text() : Color::from_rgb(0x606060);
         } else {
             if (alternating_row_colors() && (painted_item_index % 2))
                 background_color = Color(210, 210, 210);
             else
-                background_color = SystemColor::Base;
+                background_color = palette().color(background_role());
         }
 
         auto column_metadata = model()->column_metadata(m_model_column);
@@ -129,7 +131,7 @@ void GListView::paint_event(GPaintEvent& event)
             if (is_selected_row)
                 text_color = Color::White;
             else
-                text_color = model()->data(index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
+                text_color = model()->data(index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
             auto text_rect = row_rect;
             text_rect.move_by(horizontal_padding(), 0);
             text_rect.set_width(text_rect.width() - horizontal_padding() * 2);
@@ -140,7 +142,7 @@ void GListView::paint_event(GPaintEvent& event)
     };
 
     Rect unpainted_rect(0, painted_item_index * item_height(), exposed_width, height());
-    painter.fill_rect(unpainted_rect, SystemColor::Base);
+    painter.fill_rect(unpainted_rect, palette().color(background_role()));
 }
 
 int GListView::item_count() const

+ 1 - 1
Libraries/LibGUI/GProgressBar.cpp

@@ -58,5 +58,5 @@ void GProgressBar::paint_event(GPaintEvent& event)
         progress_text = builder.to_string();
     }
 
-    StylePainter::paint_progress_bar(painter, rect, m_min, m_max, m_value, progress_text);
+    StylePainter::paint_progress_bar(painter, rect, palette(), m_min, m_max, m_value, progress_text);
 }

+ 4 - 2
Libraries/LibGUI/GResizeCorner.cpp

@@ -1,11 +1,13 @@
+#include <LibDraw/GraphicsBitmap.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GPainter.h>
 #include <LibGUI/GResizeCorner.h>
 #include <LibGUI/GWindow.h>
-#include <LibDraw/GraphicsBitmap.h>
 
 GResizeCorner::GResizeCorner(GWidget* parent)
     : GWidget(parent)
 {
+    set_background_role(ColorRole::Button);
     set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
     set_preferred_size(16, 16);
     m_bitmap = GraphicsBitmap::load_from_file("/res/icons/resize-corner.png");
@@ -20,7 +22,7 @@ void GResizeCorner::paint_event(GPaintEvent& event)
 {
     GPainter painter(*this);
     painter.add_clip_rect(event.rect());
-    painter.fill_rect(rect(), SystemColor::Button);
+    painter.fill_rect(rect(), palette().color(background_role()));
     painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
     GWidget::paint_event(event);
 }

+ 7 - 6
Libraries/LibGUI/GScrollBar.cpp

@@ -1,5 +1,6 @@
 #include <LibDraw/CharacterBitmap.h>
 #include <LibDraw/GraphicsBitmap.h>
+#include <LibDraw/Palette.h>
 #include <LibDraw/StylePainter.h>
 #include <LibGUI/GPainter.h>
 #include <LibGUI/GScrollBar.h>
@@ -203,18 +204,18 @@ void GScrollBar::paint_event(GPaintEvent& event)
     GPainter painter(*this);
     painter.add_clip_rect(event.rect());
 
-    painter.fill_rect(rect(), Color(SystemColor::Button).lightened());
+    painter.fill_rect(rect(), palette().button().lightened());
 
-    StylePainter::paint_button(painter, decrement_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton);
-    StylePainter::paint_button(painter, increment_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton);
+    StylePainter::paint_button(painter, decrement_button_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton);
+    StylePainter::paint_button(painter, increment_button_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton);
 
     if (length(orientation()) > default_button_size()) {
-        painter.draw_bitmap(decrement_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? SystemColor::ButtonText : SystemColor::DisabledText);
-        painter.draw_bitmap(increment_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? SystemColor::ButtonText : SystemColor::DisabledText);
+        painter.draw_bitmap(decrement_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? palette().button_text() : palette().threed_shadow1());
+        painter.draw_bitmap(increment_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? palette().button_text() : palette().threed_shadow1());
     }
 
     if (has_scrubber())
-        StylePainter::paint_button(painter, scrubber_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber || m_scrubber_in_use);
+        StylePainter::paint_button(painter, scrubber_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber || m_scrubber_in_use);
 }
 
 void GScrollBar::on_automatic_scrolling_timer_fired()

+ 2 - 2
Libraries/LibGUI/GSlider.cpp

@@ -62,8 +62,8 @@ void GSlider::paint_event(GPaintEvent& event)
         track_rect.center_horizontally_within(inner_rect());
     }
 
-    StylePainter::paint_frame(painter, track_rect, FrameShape::Panel, FrameShadow::Sunken, 1);
-    StylePainter::paint_button(painter, knob_rect(), ButtonStyle::Normal, false, m_knob_hovered);
+    StylePainter::paint_frame(painter, track_rect, palette(), FrameShape::Panel, FrameShadow::Sunken, 1);
+    StylePainter::paint_button(painter, knob_rect(), palette(), ButtonStyle::Normal, false, m_knob_hovered);
 }
 
 Rect GSlider::knob_rect() const

+ 4 - 3
Libraries/LibGUI/GSplitter.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibGUI/GBoxLayout.h>
 #include <LibGUI/GSplitter.h>
 #include <LibGUI/GWindow.h>
@@ -6,9 +7,9 @@ GSplitter::GSplitter(Orientation orientation, GWidget* parent)
     : GFrame(parent)
     , m_orientation(orientation)
 {
+    set_background_role(ColorRole::Button);
     set_layout(make<GBoxLayout>(orientation));
     set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
     layout()->set_spacing(3);
 }
 
@@ -18,14 +19,14 @@ GSplitter::~GSplitter()
 
 void GSplitter::enter_event(CEvent&)
 {
-    set_background_color(StylePainter::hover_highlight_color());
+    set_background_role(ColorRole::HoverHighlight);
     window()->set_override_cursor(m_orientation == Orientation::Horizontal ? GStandardCursor::ResizeHorizontal : GStandardCursor::ResizeVertical);
     update();
 }
 
 void GSplitter::leave_event(CEvent&)
 {
-    set_background_color(SystemColor::Window);
+    set_background_role(ColorRole::Button);
     if (!m_resizing)
         window()->set_override_cursor(GStandardCursor::None);
     update();

+ 1 - 1
Libraries/LibGUI/GStatusBar.cpp

@@ -66,5 +66,5 @@ void GStatusBar::paint_event(GPaintEvent& event)
 {
     GPainter painter(*this);
     painter.add_clip_rect(event.rect());
-    StylePainter::paint_surface(painter, rect(), !spans_entire_window_horizontally());
+    StylePainter::paint_surface(painter, rect(), palette(), !spans_entire_window_horizontally());
 }

+ 8 - 9
Libraries/LibGUI/GTabWidget.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibDraw/StylePainter.h>
 #include <LibGUI/GBoxLayout.h>
 #include <LibGUI/GPainter.h>
@@ -6,8 +7,6 @@
 GTabWidget::GTabWidget(GWidget* parent)
     : GWidget(parent)
 {
-    set_fill_with_background_color(true);
-    set_background_color(SystemColor::Window);
 }
 
 GTabWidget::~GTabWidget()
@@ -112,19 +111,19 @@ void GTabWidget::paint_event(GPaintEvent& event)
     auto container_rect = this->container_rect();
     auto padding_rect = container_rect;
     for (int i = 0; i < container_padding(); ++i) {
-        painter.draw_rect(padding_rect, background_color());
+        painter.draw_rect(padding_rect, palette().button());
         padding_rect.shrink(2, 2);
     }
 
-    StylePainter::paint_frame(painter, container_rect, FrameShape::Container, FrameShadow::Raised, 2);
+    StylePainter::paint_frame(painter, container_rect, palette(), FrameShape::Container, FrameShadow::Raised, 2);
 
     for (int i = 0; i < m_tabs.size(); ++i) {
         if (m_tabs[i].widget == m_active_widget)
             continue;
         bool hovered = i == m_hovered_tab_index;
         auto button_rect = this->button_rect(i);
-        StylePainter::paint_tab_button(painter, button_rect, false, hovered, m_tabs[i].widget->is_enabled());
-        painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, SystemColor::ButtonText);
+        StylePainter::paint_tab_button(painter, button_rect, palette(), false, hovered, m_tabs[i].widget->is_enabled());
+        painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, palette().button_text());
     }
 
     for (int i = 0; i < m_tabs.size(); ++i) {
@@ -132,9 +131,9 @@ void GTabWidget::paint_event(GPaintEvent& event)
             continue;
         bool hovered = i == m_hovered_tab_index;
         auto button_rect = this->button_rect(i);
-        StylePainter::paint_tab_button(painter, button_rect, true, hovered, m_tabs[i].widget->is_enabled());
-        painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, SystemColor::ButtonText);
-        painter.draw_line(button_rect.bottom_left().translated(1, 1), button_rect.bottom_right().translated(-1, 1), SystemColor::Button);
+        StylePainter::paint_tab_button(painter, button_rect, palette(), true, hovered, m_tabs[i].widget->is_enabled());
+        painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, palette().button_text());
+        painter.draw_line(button_rect.bottom_left().translated(1, 1), button_rect.bottom_right().translated(-1, 1), palette().button());
         break;
     }
 }

+ 14 - 11
Libraries/LibGUI/GTableView.cpp

@@ -1,5 +1,6 @@
 #include <AK/StringBuilder.h>
 #include <Kernel/KeyCode.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GMenu.h>
 #include <LibGUI/GModel.h>
@@ -12,6 +13,7 @@
 GTableView::GTableView(GWidget* parent)
     : GAbstractColumnView(parent)
 {
+    set_background_role(ColorRole::Base);
 }
 
 GTableView::~GTableView()
@@ -20,12 +22,13 @@ GTableView::~GTableView()
 
 void GTableView::paint_event(GPaintEvent& event)
 {
+    Color widget_background_color = palette().color(background_role());
     GFrame::paint_event(event);
 
     GPainter painter(*this);
     painter.add_clip_rect(frame_inner_rect());
     painter.add_clip_rect(event.rect());
-    painter.fill_rect(event.rect(), SystemColor::Base);
+    painter.fill_rect(event.rect(), widget_background_color);
     painter.translate(frame_thickness(), frame_thickness());
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
 
@@ -53,15 +56,15 @@ void GTableView::paint_event(GPaintEvent& event)
         Color background_color;
         Color key_column_background_color;
         if (is_selected_row) {
-            background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
-            key_column_background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
+            background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
+            key_column_background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
         } else {
             if (alternating_row_colors() && (painted_item_index % 2)) {
-                background_color = Color(SystemColor::Base).darkened(0.8f);
-                key_column_background_color = Color(SystemColor::Base).darkened(0.7f);
+                background_color = widget_background_color.darkened(0.8f);
+                key_column_background_color = widget_background_color.darkened(0.7f);
             } else {
-                background_color = SystemColor::Base;
-                key_column_background_color = Color(SystemColor::Base).darkened(0.9f);
+                background_color = widget_background_color;
+                key_column_background_color = widget_background_color.darkened(0.9f);
             }
         }
         painter.fill_rect(row_rect(painted_item_index), background_color);
@@ -82,7 +85,7 @@ void GTableView::paint_event(GPaintEvent& event)
             auto cell_index = model()->index(row_index, column_index);
 
             if (auto* delegate = column_data(column_index).cell_painting_delegate.ptr()) {
-                delegate->paint(painter, cell_rect, *model(), cell_index);
+                delegate->paint(painter, cell_rect, palette(), *model(), cell_index);
             } else {
                 auto data = model()->data(cell_index);
                 if (data.is_bitmap()) {
@@ -93,9 +96,9 @@ void GTableView::paint_event(GPaintEvent& event)
                 } else {
                     Color text_color;
                     if (is_selected_row)
-                        text_color = SystemColor::SelectionText;
+                        text_color = palette().selection_text();
                     else
-                        text_color = model()->data(cell_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
+                        text_color = model()->data(cell_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
                     painter.draw_text(cell_rect, data.to_string(), font, column_metadata.text_alignment, text_color, TextElision::Right);
                 }
             }
@@ -105,7 +108,7 @@ void GTableView::paint_event(GPaintEvent& event)
     };
 
     Rect unpainted_rect(0, header_height() + painted_item_index * item_height(), exposed_width, height());
-    painter.fill_rect(unpainted_rect, SystemColor::Base);
+    painter.fill_rect(unpainted_rect, widget_background_color);
 
     // Untranslate the painter vertically and do the column headers.
     painter.translate(0, vertical_scrollbar().value());

+ 10 - 8
Libraries/LibGUI/GTextEditor.cpp

@@ -1,6 +1,7 @@
 #include <AK/QuickSort.h>
 #include <AK/StringBuilder.h>
 #include <Kernel/KeyCode.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GClipboard.h>
 #include <LibGUI/GFontDatabase.h>
@@ -295,6 +296,7 @@ Rect GTextEditor::visible_text_rect_in_inner_coordinates() const
 
 void GTextEditor::paint_event(GPaintEvent& event)
 {
+    Color widget_background_color = palette().color(background_role());
     // NOTE: This ensures that spans are updated before we look at them.
     flush_pending_change_notification_if_needed();
 
@@ -303,15 +305,15 @@ void GTextEditor::paint_event(GPaintEvent& event)
     GPainter painter(*this);
     painter.add_clip_rect(widget_inner_rect());
     painter.add_clip_rect(event.rect());
-    painter.fill_rect(event.rect(), SystemColor::Base);
+    painter.fill_rect(event.rect(), widget_background_color);
 
     painter.translate(frame_thickness(), frame_thickness());
 
     auto ruler_rect = ruler_rect_in_inner_coordinates();
 
     if (m_ruler_visible) {
-        painter.fill_rect(ruler_rect, Color(SystemColor::Base).darkened(0.85f));
-        painter.draw_line(ruler_rect.top_right(), ruler_rect.bottom_right(), Color(SystemColor::Base).darkened(0.5f));
+        painter.fill_rect(ruler_rect, widget_background_color.darkened(0.85f));
+        painter.draw_line(ruler_rect.top_right(), ruler_rect.bottom_right(), widget_background_color.darkened(0.5f));
     }
 
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
@@ -333,7 +335,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
                 String::number(i + 1),
                 is_current_line ? Font::default_bold_font() : font(),
                 TextAlignment::TopRight,
-                is_current_line ? Color(SystemColor::Base).darkened(0.6f) : Color(SystemColor::Base).darkened(0.7f));
+                is_current_line ? widget_background_color.darkened(0.6f) : widget_background_color.darkened(0.7f));
         }
     }
 
@@ -369,13 +371,13 @@ void GTextEditor::paint_event(GPaintEvent& event)
         size_t visual_line_index = 0;
         for_each_visual_line(line_index, [&](const Rect& visual_line_rect, const StringView& visual_line_text, size_t start_of_visual_line) {
             if (is_multi_line() && line_index == m_cursor.line())
-                painter.fill_rect(visual_line_rect, Color(SystemColor::Base).darkened(0.9f));
+                painter.fill_rect(visual_line_rect, widget_background_color.darkened(0.9f));
 #ifdef DEBUG_GTEXTEDITOR
             painter.draw_rect(visual_line_rect, Color::Cyan);
 #endif
             if (!document().has_spans()) {
                 // Fast-path for plain text
-                painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, SystemColor::WindowText);
+                painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, palette().color(foreground_role()));
             } else {
                 int advance = font().glyph_width(' ') + font().glyph_spacing();
                 Rect character_rect = { visual_line_rect.location(), { font().glyph_width(' '), line_height() } };
@@ -424,7 +426,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
                         visual_line_rect.height()
                     };
 
-                    painter.fill_rect(selection_rect, SystemColor::Selection);
+                    painter.fill_rect(selection_rect, palette().selection());
 
                     size_t start_of_selection_within_visual_line = (size_t)max(0, (int)selection_start_column_within_line - (int)start_of_visual_line);
                     size_t end_of_selection_within_visual_line = selection_end_column_within_line - start_of_visual_line;
@@ -434,7 +436,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
                         end_of_selection_within_visual_line - start_of_selection_within_visual_line
                     };
 
-                    painter.draw_text(selection_rect, visual_selected_text, TextAlignment::CenterLeft, SystemColor::SelectionText);
+                    painter.draw_text(selection_rect, visual_selected_text, TextAlignment::CenterLeft, palette().selection_text());
                 }
             }
             ++visual_line_index;

+ 5 - 4
Libraries/LibGUI/GToolBar.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GActionGroup.h>
 #include <LibGUI/GBoxLayout.h>
@@ -71,8 +72,8 @@ public:
         GPainter painter(*this);
         painter.add_clip_rect(event.rect());
         painter.translate(rect().center().x() - 1, 0);
-        painter.draw_line({ 0, 0 }, { 0, rect().bottom() }, SystemColor::ThreedShadow1);
-        painter.draw_line({ 1, 0 }, { 1, rect().bottom() }, SystemColor::ThreedHighlight);
+        painter.draw_line({ 0, 0 }, { 0, rect().bottom() }, palette().threed_shadow1());
+        painter.draw_line({ 1, 0 }, { 1, rect().bottom() }, palette().threed_highlight());
     }
 };
 
@@ -90,7 +91,7 @@ void GToolBar::paint_event(GPaintEvent& event)
     painter.add_clip_rect(event.rect());
 
     if (m_has_frame)
-        StylePainter::paint_surface(painter, rect(), x() != 0, y() != 0);
+        StylePainter::paint_surface(painter, rect(), palette(), x() != 0, y() != 0);
     else
-        painter.fill_rect(event.rect(), background_color());
+        painter.fill_rect(event.rect(), palette().button());
 }

+ 9 - 7
Libraries/LibGUI/GTreeView.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibGUI/GPainter.h>
 #include <LibGUI/GScrollBar.h>
 #include <LibGUI/GTreeView.h>
@@ -23,6 +24,7 @@ GTreeView::MetadataForIndex& GTreeView::ensure_metadata_for_index(const GModelIn
 GTreeView::GTreeView(GWidget* parent)
     : GAbstractColumnView(parent)
 {
+    set_background_role(ColorRole::Base);
     set_size_columns_to_fit_content(true);
     set_headers_visible(false);
     m_expand_bitmap = GraphicsBitmap::load_from_file("/res/icons/treeview-expand.png");
@@ -146,7 +148,7 @@ void GTreeView::paint_event(GPaintEvent& event)
     GPainter painter(*this);
     painter.add_clip_rect(frame_inner_rect());
     painter.add_clip_rect(event.rect());
-    painter.fill_rect(event.rect(), SystemColor::Base);
+    painter.fill_rect(event.rect(), palette().color(background_role()));
 
     if (!model())
         return;
@@ -178,21 +180,21 @@ void GTreeView::paint_event(GPaintEvent& event)
 
         bool is_selected_row = selection().contains(index);
 
-        Color text_color = SystemColor::WindowText;
+        Color text_color = palette().color(foreground_role());
         if (is_selected_row)
             text_color = Color::White;
 
         Color background_color;
         Color key_column_background_color;
         if (is_selected_row) {
-            background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
-            key_column_background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
+            background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
+            key_column_background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
         } else {
             if (alternating_row_colors() && (painted_row_index % 2)) {
                 background_color = Color(220, 220, 220);
                 key_column_background_color = Color(200, 200, 200);
             } else {
-                background_color = SystemColor::Base;
+                background_color = palette().color(background_role());
                 key_column_background_color = Color(220, 220, 220);
             }
         }
@@ -215,7 +217,7 @@ void GTreeView::paint_event(GPaintEvent& event)
                 auto cell_index = model.sibling(index.row(), column_index, index.parent());
 
                 if (auto* delegate = column_data(column_index).cell_painting_delegate.ptr()) {
-                    delegate->paint(painter, cell_rect, model, cell_index);
+                    delegate->paint(painter, cell_rect, palette(), model, cell_index);
                 } else {
                     auto data = model.data(cell_index);
 
@@ -226,7 +228,7 @@ void GTreeView::paint_event(GPaintEvent& event)
                             painter.blit(cell_rect.location(), *bitmap, bitmap->rect());
                     } else {
                         if (!is_selected_row)
-                            text_color = model.data(cell_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
+                            text_color = model.data(cell_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
                         painter.draw_text(cell_rect, data.to_string(), font, column_metadata.text_alignment, text_color, TextElision::Right);
                     }
                 }

+ 16 - 12
Libraries/LibGUI/GWidget.cpp

@@ -1,26 +1,26 @@
 #include <AK/Assertions.h>
 #include <AK/JsonObject.h>
 #include <LibDraw/GraphicsBitmap.h>
+#include <LibDraw/Palette.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GApplication.h>
-#include <LibGUI/GEvent.h>
-#include <LibGUI/GLayout.h>
-#include <LibGUI/GMenu.h>
-#include <LibGUI/GPainter.h>
-#include <LibGUI/GWidget.h>
-#include <LibGUI/GWindow.h>
-#include <LibGUI/GWindowServerConnection.h>
-#include <unistd.h>
-
 #include <LibGUI/GButton.h>
 #include <LibGUI/GCheckBox.h>
+#include <LibGUI/GEvent.h>
 #include <LibGUI/GGroupBox.h>
 #include <LibGUI/GLabel.h>
+#include <LibGUI/GLayout.h>
+#include <LibGUI/GMenu.h>
+#include <LibGUI/GPainter.h>
 #include <LibGUI/GRadioButton.h>
 #include <LibGUI/GScrollBar.h>
 #include <LibGUI/GSlider.h>
 #include <LibGUI/GSpinBox.h>
 #include <LibGUI/GTextBox.h>
+#include <LibGUI/GWidget.h>
+#include <LibGUI/GWindow.h>
+#include <LibGUI/GWindowServerConnection.h>
+#include <unistd.h>
 
 REGISTER_GWIDGET(GButton)
 REGISTER_GWIDGET(GCheckBox)
@@ -67,9 +67,8 @@ const GWidgetClassRegistration* GWidgetClassRegistration::find(const String& cla
 GWidget::GWidget(GWidget* parent)
     : CObject(parent, true)
     , m_font(Font::default_font())
+    , m_palette(GApplication::the().palette())
 {
-    m_background_color = SystemColor::Window;
-    m_foreground_color = SystemColor::WindowText;
 }
 
 GWidget::~GWidget()
@@ -173,7 +172,7 @@ void GWidget::handle_paint_event(GPaintEvent& event)
     ASSERT(is_visible());
     if (fill_with_background_color()) {
         GPainter painter(*this);
-        painter.fill_rect(event.rect(), background_color());
+        painter.fill_rect(event.rect(), palette().color(background_role()));
     } else {
 #ifdef DEBUG_WIDGET_UNDERDRAW
         // FIXME: This is a bit broken.
@@ -693,3 +692,8 @@ Vector<GWidget*> GWidget::child_widgets() const
     }
     return widgets;
 }
+
+void GWidget::set_palette(const Palette& palette)
+{
+    m_palette = palette;
+}

+ 16 - 1
Libraries/LibGUI/GWidget.h

@@ -9,6 +9,7 @@
 #include <LibDraw/Font.h>
 #include <LibDraw/Orientation.h>
 #include <LibDraw/Rect.h>
+#include <LibDraw/SystemTheme.h>
 #include <LibGUI/GEvent.h>
 #include <LibGUI/GShortcut.h>
 
@@ -16,11 +17,12 @@
     extern GWidgetClassRegistration registration_##class_name; \
     GWidgetClassRegistration registration_##class_name(#class_name, [](GWidget* parent) { return class_name::construct(parent); });
 
-class GraphicsBitmap;
 class GAction;
 class GLayout;
 class GMenu;
 class GWindow;
+class GraphicsBitmap;
+class Palette;
 
 enum class SizePolicy {
     Fixed,
@@ -149,6 +151,12 @@ public:
     void move_by(int x, int y) { move_by({ x, y }); }
     void move_by(const Point& delta) { set_relative_rect({ relative_position().translated(delta), size() }); }
 
+    ColorRole background_role() const { return m_background_role; }
+    void set_background_role(ColorRole role) { m_background_role = role; }
+
+    ColorRole foreground_role() const { return m_foreground_role; }
+    void set_foreground_role(ColorRole role) { m_foreground_role = role; }
+
     Color background_color() const { return m_background_color; }
     Color foreground_color() const { return m_foreground_color; }
 
@@ -230,6 +238,9 @@ public:
 
     void do_layout();
 
+    const Palette& palette() const { return *m_palette; }
+    void set_palette(const Palette&);
+
 protected:
     explicit GWidget(GWidget* parent = nullptr);
 
@@ -271,6 +282,8 @@ private:
     OwnPtr<GLayout> m_layout;
 
     Rect m_relative_rect;
+    ColorRole m_background_role { ColorRole::Window };
+    ColorRole m_foreground_role { ColorRole::WindowText };
     Color m_background_color;
     Color m_foreground_color;
     NonnullRefPtr<Font> m_font;
@@ -288,6 +301,8 @@ private:
     bool m_updates_enabled { true };
 
     HashMap<GShortcut, GAction*> m_local_shortcut_actions;
+
+    NonnullRefPtr<Palette> m_palette;
 };
 
 template<>

+ 2 - 0
Libraries/LibGUI/GWindowServerConnection.cpp

@@ -1,3 +1,4 @@
+#include <LibDraw/Palette.h>
 #include <LibDraw/SystemTheme.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GApplication.h>
@@ -25,6 +26,7 @@ static void set_system_theme_from_shared_buffer_id(int id)
     auto system_theme = SharedBuffer::create_from_shared_buffer_id(id);
     ASSERT(system_theme);
     set_system_theme(*system_theme);
+    GApplication::the().set_system_palette(*system_theme);
 }
 
 void GWindowServerConnection::handshake()

+ 2 - 2
Libraries/LibHTML/HtmlView.cpp

@@ -118,7 +118,7 @@ void HtmlView::paint_event(GPaintEvent& event)
     painter.add_clip_rect(event.rect());
 
     if (!layout_root()) {
-        painter.fill_rect(event.rect(), background_color());
+        painter.fill_rect(event.rect(), palette().color(background_role()));
         return;
     }
 
@@ -131,7 +131,7 @@ void HtmlView::paint_event(GPaintEvent& event)
     painter.translate(frame_thickness(), frame_thickness());
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
 
-    RenderingContext context { painter };
+    RenderingContext context(painter, palette());
     context.set_should_show_line_box_borders(m_should_show_line_box_borders);
     context.set_viewport_rect(visible_content_rect());
     layout_root()->render(context);

+ 1 - 1
Libraries/LibHTML/Layout/LayoutImage.cpp

@@ -43,7 +43,7 @@ void LayoutImage::render(RenderingContext& context)
 
     if (renders_as_alt_text()) {
         context.painter().set_font(Font::default_font());
-        StylePainter::paint_frame(context.painter(), enclosing_int_rect(rect()), FrameShape::Container, FrameShadow::Sunken, 2);
+        StylePainter::paint_frame(context.painter(), enclosing_int_rect(rect()), context.palette(), FrameShape::Container, FrameShadow::Sunken, 2);
         auto alt = node().alt();
         if (alt.is_empty())
             alt = node().src();

+ 5 - 1
Libraries/LibHTML/RenderingContext.h

@@ -1,17 +1,20 @@
 #pragma once
 
+#include <LibDraw/Palette.h>
 #include <LibDraw/Rect.h>
 
 class GPainter;
 
 class RenderingContext {
 public:
-    explicit RenderingContext(GPainter& painter)
+    explicit RenderingContext(GPainter& painter, const Palette& palette)
         : m_painter(painter)
+        , m_palette(palette)
     {
     }
 
     GPainter& painter() const { return m_painter; }
+    const Palette& palette() const { return m_palette; }
 
     bool should_show_line_box_borders() const { return m_should_show_line_box_borders; }
     void set_should_show_line_box_borders(bool value) { m_should_show_line_box_borders = value; }
@@ -21,6 +24,7 @@ public:
 
 private:
     GPainter& m_painter;
+    const Palette& m_palette;
     Rect m_viewport_rect;
     bool m_should_show_line_box_borders { false };
 };

+ 3 - 2
Servers/WindowServer/WSButton.cpp

@@ -18,14 +18,15 @@ WSButton::~WSButton()
 
 void WSButton::paint(Painter& painter)
 {
+    auto& palette = WSWindowManager::the().palette();
     PainterStateSaver saver(painter);
     painter.translate(relative_rect().location());
-    StylePainter::paint_button(painter, rect(), ButtonStyle::Normal, m_pressed, m_hovered);
+    StylePainter::paint_button(painter, rect(), palette, 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, SystemColor::ButtonText);
+    painter.draw_bitmap(x_location, *m_bitmap, palette.button_text());
 }
 
 void WSButton::on_mouse_event(const WSMouseEvent& event)

+ 1 - 1
Servers/WindowServer/WSCompositor.cpp

@@ -113,7 +113,7 @@ void WSCompositor::compose()
         if (wm.any_opaque_window_contains_rect(dirty_rect))
             continue;
         // FIXME: If the wallpaper is opaque, no need to fill with color!
-        m_back_painter->fill_rect(dirty_rect, SystemColor::DesktopBackground);
+        m_back_painter->fill_rect(dirty_rect, wm.palette().desktop_background());
         if (m_wallpaper) {
             if (m_wallpaper_mode == WallpaperMode::Simple) {
                 m_back_painter->blit(dirty_rect.location(), *m_wallpaper, dirty_rect);

+ 14 - 13
Servers/WindowServer/WSMenu.cpp

@@ -126,6 +126,7 @@ WSWindow& WSMenu::ensure_menu_window()
 
 void WSMenu::draw()
 {
+    auto& palette = WSWindowManager::the().palette();
     m_theme_index_at_last_paint = WSWindowManager::the().theme_index();
 
     ASSERT(menu_window());
@@ -133,8 +134,8 @@ void WSMenu::draw()
     Painter painter(*menu_window()->backing_store());
 
     Rect rect { {}, menu_window()->size() };
-    painter.fill_rect(rect.shrunken(6, 6), SystemColor::MenuBase);
-    StylePainter::paint_window_frame(painter, rect);
+    painter.fill_rect(rect.shrunken(6, 6), palette.menu_base());
+    StylePainter::paint_window_frame(painter, rect, palette);
     int width = this->width();
 
     if (!s_checked_bitmap)
@@ -148,15 +149,15 @@ void WSMenu::draw()
     }
 
     Rect stripe_rect { frame_thickness(), frame_thickness(), s_stripe_width, height() - frame_thickness() * 2 };
-    painter.fill_rect(stripe_rect, SystemColor::MenuStripe);
-    painter.draw_line(stripe_rect.top_right(), stripe_rect.bottom_right(), Color(SystemColor::MenuStripe).darkened());
+    painter.fill_rect(stripe_rect, palette.menu_stripe());
+    painter.draw_line(stripe_rect.top_right(), stripe_rect.bottom_right(), palette.menu_stripe().darkened());
 
     for (auto& item : m_items) {
         if (item.type() == WSMenuItem::Text) {
-            Color text_color = SystemColor::WindowText;
+            Color text_color = palette.window_text();
             if (&item == m_hovered_item && item.is_enabled()) {
-                painter.fill_rect(item.rect(), SystemColor::MenuSelection);
-                painter.draw_rect(item.rect(), Color(SystemColor::MenuSelection).darkened());
+                painter.fill_rect(item.rect(), palette.menu_selection());
+                painter.draw_rect(item.rect(), palette.menu_selection().darkened());
                 text_color = Color::White;
             } else if (!item.is_enabled()) {
                 text_color = Color::MidGray;
@@ -166,10 +167,10 @@ void WSMenu::draw()
                 Rect checkmark_rect { item.rect().x() + 7, 0, s_checked_bitmap_width, s_checked_bitmap_height };
                 checkmark_rect.center_vertically_within(text_rect);
                 Rect checkbox_rect = checkmark_rect.inflated(4, 4);
-                painter.fill_rect(checkbox_rect, SystemColor::Base);
-                StylePainter::paint_frame(painter, checkbox_rect, FrameShape::Container, FrameShadow::Sunken, 2);
+                painter.fill_rect(checkbox_rect, palette.base());
+                StylePainter::paint_frame(painter, checkbox_rect, palette, FrameShape::Container, FrameShadow::Sunken, 2);
                 if (item.is_checked()) {
-                    painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, SystemColor::ButtonText);
+                    painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, palette.button_text());
                 }
             } else if (item.icon()) {
                 Rect icon_rect { item.rect().x() + 3, 0, s_item_icon_width, s_item_icon_width };
@@ -189,13 +190,13 @@ void WSMenu::draw()
                     s_submenu_arrow_bitmap_height
                 };
                 submenu_arrow_rect.center_vertically_within(item.rect());
-                painter.draw_bitmap(submenu_arrow_rect.location(), submenu_arrow_bitmap, SystemColor::WindowText);
+                painter.draw_bitmap(submenu_arrow_rect.location(), submenu_arrow_bitmap, palette.window_text());
             }
         } else if (item.type() == WSMenuItem::Separator) {
             Point p1(item.rect().translated(stripe_rect.width() + 4, 0).x(), item.rect().center().y() - 1);
             Point p2(width - 7, item.rect().center().y() - 1);
-            painter.draw_line(p1, p2, SystemColor::ThreedShadow1);
-            painter.draw_line(p1.translated(0, 1), p2.translated(0, 1), SystemColor::ThreedHighlight);
+            painter.draw_line(p1, p2, palette.threed_shadow1());
+            painter.draw_line(p1.translated(0, 1), p2.translated(0, 1), palette.threed_highlight());
         }
     }
 }

+ 8 - 7
Servers/WindowServer/WSMenuManager.cpp

@@ -44,6 +44,7 @@ bool WSMenuManager::is_open(const WSMenu& menu) const
 void WSMenuManager::draw()
 {
     auto& wm = WSWindowManager::the();
+    auto& palette = wm.palette();
     auto menubar_rect = this->menubar_rect();
 
     if (m_needs_window_resize) {
@@ -83,14 +84,14 @@ void WSMenuManager::draw()
 
     Painter painter(*window().backing_store());
 
-    painter.fill_rect(menubar_rect, SystemColor::Window);
-    painter.draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, SystemColor::ThreedShadow1);
+    painter.fill_rect(menubar_rect, palette.window());
+    painter.draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, palette.threed_shadow1());
     int index = 0;
     wm.for_each_active_menubar_menu([&](WSMenu& menu) {
-        Color text_color = SystemColor::WindowText;
+        Color text_color = palette.window_text();
         if (is_open(menu)) {
-            painter.fill_rect(menu.rect_in_menubar(), SystemColor::MenuSelection);
-            painter.draw_rect(menu.rect_in_menubar(), Color(SystemColor::MenuSelection).darkened());
+            painter.fill_rect(menu.rect_in_menubar(), palette.menu_selection());
+            painter.draw_rect(menu.rect_in_menubar(), palette.menu_selection().darkened());
             text_color = Color::White;
         }
         painter.draw_text(
@@ -103,7 +104,7 @@ void WSMenuManager::draw()
         return IterationDecision::Continue;
     });
 
-    painter.draw_text(m_username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, SystemColor::WindowText);
+    painter.draw_text(m_username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, palette.window_text());
 
     time_t now = time(nullptr);
     auto* tm = localtime(&now);
@@ -115,7 +116,7 @@ void WSMenuManager::draw()
         tm->tm_min,
         tm->tm_sec);
 
-    painter.draw_text(m_time_rect, time_text, wm.font(), TextAlignment::CenterRight, SystemColor::WindowText);
+    painter.draw_text(m_time_rect, time_text, wm.font(), TextAlignment::CenterRight, palette.window_text());
 
     for (auto& applet : m_applets) {
         if (!applet)

+ 15 - 14
Servers/WindowServer/WSWindowFrame.cpp

@@ -153,6 +153,7 @@ void WSWindowFrame::paint(Painter& painter)
     if (m_window.type() != WSWindowType::Normal)
         return;
 
+    auto& palette = WSWindowManager::the().palette();
     auto& window = m_window;
 
     auto titlebar_rect = title_bar_rect();
@@ -170,29 +171,29 @@ void WSWindowFrame::paint(Painter& painter)
     auto& wm = WSWindowManager::the();
 
     if (&window == wm.m_highlight_window) {
-        border_color = SystemColor::HighlightWindowBorder1;
-        border_color2 = SystemColor::HighlightWindowBorder2;
-        title_color = SystemColor::HighlightWindowTitle;
+        border_color = palette.highlight_window_border1();
+        border_color2 = palette.highlight_window_border2();
+        title_color = palette.highlight_window_title();
     } else if (&window == wm.m_move_window) {
-        border_color = SystemColor::MovingWindowBorder1;
-        border_color2 = SystemColor::MovingWindowBorder2;
-        title_color = SystemColor::MovingWindowTitle;
+        border_color = palette.moving_window_border1();
+        border_color2 = palette.moving_window_border2();
+        title_color = palette.moving_window_title();
     } else if (&window == wm.m_active_window) {
-        border_color = SystemColor::ActiveWindowBorder1;
-        border_color2 = SystemColor::ActiveWindowBorder2;
-        title_color = SystemColor::ActiveWindowTitle;
+        border_color = palette.active_window_border1();
+        border_color2 = palette.active_window_border2();
+        title_color = palette.active_window_title();
     } else {
-        border_color = SystemColor::InactiveWindowBorder1;
-        border_color2 = SystemColor::InactiveWindowBorder2;
-        title_color = SystemColor::InactiveWindowTitle;
+        border_color = palette.inactive_window_border1();
+        border_color2 = palette.inactive_window_border2();
+        title_color = palette.inactive_window_title();
     }
 
-    StylePainter::paint_window_frame(painter, outer_rect);
+    StylePainter::paint_window_frame(painter, outer_rect, palette);
 
     if (!window.show_titlebar())
         return;
 
-    painter.draw_line(titlebar_rect.bottom_left().translated(0, 1), titlebar_rect.bottom_right().translated(0, 1), SystemColor::Button);
+    painter.draw_line(titlebar_rect.bottom_left().translated(0, 1), titlebar_rect.bottom_right().translated(0, 1), palette.button());
 
     auto leftmost_button_rect = m_buttons.is_empty() ? Rect() : m_buttons.last().relative_rect();
 

+ 3 - 1
Servers/WindowServer/WSWindowManager.cpp

@@ -42,7 +42,8 @@ WSWindowManager& WSWindowManager::the()
     return *s_the;
 }
 
-WSWindowManager::WSWindowManager()
+WSWindowManager::WSWindowManager(const Palette& palette)
+    : m_palette(palette)
 {
     s_the = this;
 
@@ -132,6 +133,7 @@ WSWindowManager::WSWindowManager()
         auto new_theme = load_system_theme(theme.path);
         ASSERT(new_theme);
         set_system_theme(*new_theme);
+        m_palette = Palette::create_with_shared_buffer(*new_theme);
         HashTable<WSClientConnection*> notified_clients;
         for_each_window([&](WSWindow& window) {
             if (window.client()) {

+ 10 - 2
Servers/WindowServer/WSWindowManager.h

@@ -9,6 +9,7 @@
 #include <LibDraw/Color.h>
 #include <LibDraw/DisjointRectSet.h>
 #include <LibDraw/Painter.h>
+#include <LibDraw/Palette.h>
 #include <LibDraw/Rect.h>
 #include <WindowServer/WSCursor.h>
 #include <WindowServer/WSEvent.h>
@@ -50,10 +51,15 @@ class WSWindowManager : public CObject {
 public:
     static WSWindowManager& the();
 
-    WSWindowManager();
+    explicit WSWindowManager(const Palette&);
     virtual ~WSWindowManager() override;
 
-    RefPtr<CConfigFile> wm_config() const { return m_wm_config; }
+    const Palette& palette() const { return *m_palette; }
+
+    RefPtr<CConfigFile> wm_config() const
+    {
+        return m_wm_config;
+    }
     void reload_config(bool);
 
     void add_window(WSWindow&);
@@ -276,6 +282,8 @@ private:
     WeakPtr<WSButton> m_cursor_tracking_button;
     WeakPtr<WSButton> m_hovered_button;
 
+    NonnullRefPtr<Palette> m_palette;
+
     RefPtr<CConfigFile> m_wm_config;
 
     struct AppMetadata {

+ 10 - 9
Servers/WindowServer/WSWindowSwitcher.cpp

@@ -70,9 +70,10 @@ void WSWindowSwitcher::on_key_event(const WSKeyEvent& event)
 
 void WSWindowSwitcher::draw()
 {
+    auto& palette = WSWindowManager::the().palette();
     Painter painter(*m_switcher_window->backing_store());
-    painter.fill_rect({ {}, m_rect.size() }, SystemColor::Window);
-    painter.draw_rect({ {}, m_rect.size() }, SystemColor::ThreedShadow2);
+    painter.fill_rect({ {}, m_rect.size() }, palette.window());
+    painter.draw_rect({ {}, m_rect.size() }, palette.threed_shadow2());
     for (int index = 0; index < m_windows.size(); ++index) {
         auto& window = *m_windows.at(index);
         Rect item_rect {
@@ -84,21 +85,21 @@ void WSWindowSwitcher::draw()
         Color text_color;
         Color rect_text_color;
         if (index == m_selected_index) {
-            painter.fill_rect(item_rect, SystemColor::Selection);
-            text_color = SystemColor::SelectionText;
-            rect_text_color = SystemColor::ThreedShadow1;
+            painter.fill_rect(item_rect, palette.selection());
+            text_color = palette.selection_text();
+            rect_text_color = palette.threed_shadow1();
         } else {
-            text_color = SystemColor::WindowText;
-            rect_text_color = SystemColor::ThreedShadow2;
+            text_color = palette.window_text();
+            rect_text_color = palette.threed_shadow2();
         }
         item_rect.shrink(item_padding(), 0);
         Rect thumbnail_rect = { item_rect.location().translated(0, 5), { thumbnail_width(), thumbnail_height() } };
         if (window.backing_store()) {
             painter.draw_scaled_bitmap(thumbnail_rect, *window.backing_store(), window.backing_store()->rect());
-            StylePainter::paint_frame(painter, thumbnail_rect.inflated(4, 4), FrameShape::Container, FrameShadow::Sunken, 2);
+            StylePainter::paint_frame(painter, thumbnail_rect.inflated(4, 4), palette, FrameShape::Container, FrameShadow::Sunken, 2);
         }
         Rect icon_rect = { thumbnail_rect.bottom_right().translated(-window.icon().width(), -window.icon().height()), { window.icon().width(), window.icon().height() } };
-        painter.fill_rect(icon_rect, SystemColor::Window);
+        painter.fill_rect(icon_rect, palette.window());
         painter.blit(icon_rect.location(), window.icon(), window.icon().rect());
         painter.draw_text(item_rect.translated(thumbnail_width() + 12, 0), window.title(), WSWindowManager::the().window_title_font(), TextAlignment::CenterLeft, text_color);
         painter.draw_text(item_rect, window.rect().to_string(), TextAlignment::CenterRight, rect_text_color);

+ 3 - 1
Servers/WindowServer/main.cpp

@@ -1,4 +1,5 @@
 #include <LibCore/CConfigFile.h>
+#include <LibDraw/Palette.h>
 #include <LibDraw/SystemTheme.h>
 #include <WindowServer/WSCompositor.h>
 #include <WindowServer/WSEventLoop.h>
@@ -25,13 +26,14 @@ int main(int, char**)
     auto theme = load_system_theme(String::format("/res/themes/%s.ini", theme_name.characters()));
     ASSERT(theme);
     set_system_theme(*theme);
+    auto palette = Palette::create_with_shared_buffer(*theme);
 
     WSEventLoop loop;
 
     WSScreen screen(wm_config->read_num_entry("Screen", "Width", 1024),
         wm_config->read_num_entry("Screen", "Height", 768));
     WSCompositor::the();
-    auto wm = WSWindowManager::construct();
+    auto wm = WSWindowManager::construct(*palette);
 
     dbgprintf("Entering WindowServer main loop.\n");
     loop.exec();