summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2021-05-28 21:26:39 +0200
committerLinus Groh <mail@linusgroh.de>2021-06-04 09:02:43 +0100
commitacbd1d14d0ca8ea063a9acaec988913557acd22b (patch)
treec5b38b2d961a6e0dc96bce594159e8af9710ca4c /Userland
parent99033876ec6fc7484d7967d6cbd64f79669c21f7 (diff)
downloadserenity-acbd1d14d0ca8ea063a9acaec988913557acd22b.zip
LibVT+Terminal: Add color scheme support
This commit introduces color scheme support to Terminal. These are found in `/res/terminal_colors` and the default color scheme can be set in `~/.config/Terminal.ini`. Furthermore, a combo box is added for setting the color scheme at runtime. The previously used default color scheme has been added to `/res/terminal-colors/Default.ini`. To make the implementation more compatible with other color schemes, `TerminalWidget` now supports overriding the default foreground and background colors.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Applications/Terminal/TerminalSettingsWindow.gml13
-rw-r--r--Userland/Applications/Terminal/main.cpp25
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.cpp61
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.h10
4 files changed, 104 insertions, 5 deletions
diff --git a/Userland/Applications/Terminal/TerminalSettingsWindow.gml b/Userland/Applications/Terminal/TerminalSettingsWindow.gml
index 07b8400c56..6c906fd463 100644
--- a/Userland/Applications/Terminal/TerminalSettingsWindow.gml
+++ b/Userland/Applications/Terminal/TerminalSettingsWindow.gml
@@ -60,4 +60,17 @@
orientation: "Horizontal"
}
}
+
+ @GUI::GroupBox {
+ title: "Color scheme"
+ shrink_to_fit: true
+
+ layout: @GUI::VerticalBoxLayout {
+ margins: [6, 16, 6, 6]
+ }
+
+ @GUI::ComboBox {
+ name: "color_scheme_combo"
+ }
+ }
}
diff --git a/Userland/Applications/Terminal/main.cpp b/Userland/Applications/Terminal/main.cpp
index 846b0ffdd2..dd8fc9e325 100644
--- a/Userland/Applications/Terminal/main.cpp
+++ b/Userland/Applications/Terminal/main.cpp
@@ -4,10 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <AK/QuickSort.h>
#include <AK/URL.h>
#include <Applications/Terminal/TerminalSettingsWindowGML.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/ConfigFile.h>
+#include <LibCore/DirIterator.h>
#include <LibCore/File.h>
#include <LibDesktop/Launcher.h>
#include <LibGUI/Action.h>
@@ -16,9 +18,11 @@
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/CheckBox.h>
+#include <LibGUI/ComboBox.h>
#include <LibGUI/Event.h>
#include <LibGUI/FontPicker.h>
#include <LibGUI/Icon.h>
+#include <LibGUI/ItemListModel.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Menubar.h>
#include <LibGUI/OpacitySlider.h>
@@ -105,7 +109,7 @@ static RefPtr<GUI::Window> create_settings_window(VT::TerminalWidget& terminal)
window->set_window_type(GUI::WindowType::ToolWindow);
window->set_title("Terminal settings");
window->set_resizable(false);
- window->resize(200, 210);
+ window->resize(200, 240);
window->center_within(*terminal.window());
auto& settings = window->set_main_widget<GUI::Widget>();
@@ -149,6 +153,25 @@ static RefPtr<GUI::Window> create_settings_window(VT::TerminalWidget& terminal)
terminal.set_max_history_size(value);
};
+ // The settings window takes a reference to this vector, so it needs to outlive this scope.
+ // As long as we ensure that only one settings window may be open at a time (which we do),
+ // this should cause no problems.
+ static Vector<String> color_scheme_names;
+ color_scheme_names.clear();
+ Core::DirIterator iterator("/res/terminal-colors", Core::DirIterator::SkipParentAndBaseDir);
+ while (iterator.has_next()) {
+ auto path = iterator.next_path();
+ path.replace(".ini", "");
+ color_scheme_names.append(path);
+ }
+ quick_sort(color_scheme_names);
+ auto& color_scheme_combo = *settings.find_descendant_of_type_named<GUI::ComboBox>("color_scheme_combo");
+ color_scheme_combo.set_only_allow_values_from_model(true);
+ color_scheme_combo.set_model(*GUI::ItemListModel<String>::create(color_scheme_names));
+ color_scheme_combo.set_selected_index(color_scheme_names.find_first_index(terminal.color_scheme_name()).value());
+ color_scheme_combo.on_change = [&](auto&, const GUI::ModelIndex& index) {
+ terminal.set_color_scheme(index.data().as_string());
+ };
return window;
}
diff --git a/Userland/Libraries/LibVT/TerminalWidget.cpp b/Userland/Libraries/LibVT/TerminalWidget.cpp
index 6998a8a96d..f010e8ed69 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.cpp
+++ b/Userland/Libraries/LibVT/TerminalWidget.cpp
@@ -79,6 +79,9 @@ TerminalWidget::TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<Co
, m_automatic_size_policy(automatic_size_policy)
, m_config(move(config))
{
+ static_assert(sizeof(m_colors) == sizeof(xterm_colors));
+ memcpy(m_colors, xterm_colors, sizeof(m_colors));
+
set_override_cursor(Gfx::StandardCursor::IBeam);
set_focus_policy(GUI::FocusPolicy::StrongFocus);
set_accepts_emoji_input(true);
@@ -147,6 +150,8 @@ TerminalWidget::TerminalWidget(int ptm_fd, bool automatic_size_policy, RefPtr<Co
update_copy_action();
update_paste_action();
+
+ set_color_scheme(m_config->read_entry("Window", "ColorScheme", "Default"));
}
TerminalWidget::~TerminalWidget()
@@ -1135,6 +1140,54 @@ void TerminalWidget::update_paste_action()
m_paste_action->set_enabled(GUI::Clipboard::the().mime_type().starts_with("text/") && !GUI::Clipboard::the().data().is_empty());
}
+void TerminalWidget::set_color_scheme(const StringView& name)
+{
+ if (name.contains('/')) {
+ dbgln("Shenanigans! Color scheme names can't contain slashes.");
+ return;
+ }
+
+ m_color_scheme_name = name;
+
+ constexpr StringView color_names[] = {
+ "Black",
+ "Red",
+ "Green",
+ "Yellow",
+ "Blue",
+ "Magenta",
+ "Cyan",
+ "White"
+ };
+
+ auto color_config = Core::ConfigFile::open(String::formatted("/res/terminal-colors/{}.ini", name));
+
+ auto default_background = Gfx::Color::from_string(color_config->read_entry("Primary", "Background"));
+ if (default_background.has_value())
+ m_default_background_color = default_background.value();
+ else
+ m_default_background_color = Gfx::Color::from_rgb(m_colors[(u8)VT::Color::ANSIColor::Black]);
+
+ auto default_foreground = Gfx::Color::from_string(color_config->read_entry("Primary", "Foreground"));
+ if (default_foreground.has_value())
+ m_default_foreground_color = default_foreground.value();
+ else
+ m_default_foreground_color = Gfx::Color::from_rgb(m_colors[(u8)VT::Color::ANSIColor::White]);
+
+ for (u8 color_idx = 0; color_idx < 8; ++color_idx) {
+ auto rgb = Gfx::Color::from_string(color_config->read_entry("Normal", color_names[color_idx]));
+ if (rgb.has_value())
+ m_colors[color_idx] = rgb.value().value();
+ }
+
+ for (u8 color_idx = 0; color_idx < 8; ++color_idx) {
+ auto rgb = Gfx::Color::from_string(color_config->read_entry("Bright", color_names[color_idx]));
+ if (rgb.has_value())
+ m_colors[color_idx + 8] = rgb.value().value();
+ }
+ update();
+}
+
Gfx::IntSize TerminalWidget::widget_size_for_font(const Gfx::Font& font) const
{
return {
@@ -1149,15 +1202,15 @@ Gfx::Color TerminalWidget::terminal_color_to_rgb(VT::Color color)
case VT::Color::Kind::RGB:
return Gfx::Color::from_rgb(color.as_rgb());
case VT::Color::Kind::Indexed:
- return Gfx::Color::from_rgb(xterm_colors[color.as_indexed()]);
+ return Gfx::Color::from_rgb(m_colors[color.as_indexed()]);
case VT::Color::Kind::Named: {
auto ansi = color.as_named();
if ((u16)ansi < 256)
- return Gfx::Color::from_rgb(xterm_colors[(u16)ansi]);
+ return Gfx::Color::from_rgb(m_colors[(u16)ansi]);
else if (ansi == VT::Color::ANSIColor::DefaultForeground)
- return Gfx::Color::from_rgb(xterm_colors[7]);
+ return m_default_foreground_color;
else if (ansi == VT::Color::ANSIColor::DefaultBackground)
- return Gfx::Color::from_rgb(xterm_colors[0]);
+ return m_default_background_color;
else
VERIFY_NOT_REACHED();
}
diff --git a/Userland/Libraries/LibVT/TerminalWidget.h b/Userland/Libraries/LibVT/TerminalWidget.h
index 39d8a7f2e9..5d4307e651 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.h
+++ b/Userland/Libraries/LibVT/TerminalWidget.h
@@ -81,6 +81,8 @@ public:
void paste();
void clear_including_history();
+ const StringView color_scheme_name() const { return m_color_scheme_name; }
+
Function<void(const StringView&)> on_title_change;
Function<void(const Gfx::IntSize&)> on_terminal_size_change;
Function<void()> on_command_exit;
@@ -91,6 +93,8 @@ public:
void set_font_and_resize_to_fit(const Gfx::Font&);
+ void set_color_scheme(const StringView&);
+
private:
// ^GUI::Widget
virtual void event(Core::Event&) override;
@@ -157,6 +161,12 @@ private:
// Snapshot of m_hovered_href when opening a context menu for a hyperlink.
String m_context_menu_href;
+ unsigned m_colors[256];
+ Gfx::Color m_default_foreground_color;
+ Gfx::Color m_default_background_color;
+
+ String m_color_scheme_name;
+
BellMode m_bell_mode { BellMode::Visible };
bool m_alt_key_held { false };
bool m_rectangle_selection { false };