From 1ff48a3ca4a015d7bf1f7419e5a79ab47657b933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Sun, 21 Nov 2021 01:01:21 +0100 Subject: [PATCH] Terminal: Modernize terminal settings as a standalone application The settings for Terminal are extracted into their own application, TerminalSettings, which is reachable over the normal Settings menu as well as the same place in the Terminal menu. The font settings are moved into these settings as well, which are now split up into the "Terminal" and "View" tabs. The font settings themselves receive an option to override the selected font with the system default on the user side. The live update behavior of all of the terminal settings is retained. The layout of the new TerminalSettings is based around the other Settings applications, but pixel-perfectness is missing in some places. It's a bit fiddly and I'd like to have some better GUI::Label auto-size behavior, but oh well :^) --- Base/res/apps/TerminalSettings.af | 5 + Userland/Applications/CMakeLists.txt | 1 + Userland/Applications/Terminal/CMakeLists.txt | 3 - .../Terminal/TerminalSettingsWindow.gml | 76 ------- Userland/Applications/Terminal/main.cpp | 169 +++++--------- .../TerminalSettings/CMakeLists.txt | 18 ++ .../TerminalSettings/TerminalSettingsMain.gml | 63 ++++++ .../TerminalSettings/TerminalSettingsView.gml | 82 +++++++ .../TerminalSettingsWidget.cpp | 210 ++++++++++++++++++ .../TerminalSettings/TerminalSettingsWidget.h | 53 +++++ .../Applications/TerminalSettings/main.cpp | 59 +++++ 11 files changed, 546 insertions(+), 193 deletions(-) create mode 100644 Base/res/apps/TerminalSettings.af delete mode 100644 Userland/Applications/Terminal/TerminalSettingsWindow.gml create mode 100644 Userland/Applications/TerminalSettings/CMakeLists.txt create mode 100644 Userland/Applications/TerminalSettings/TerminalSettingsMain.gml create mode 100644 Userland/Applications/TerminalSettings/TerminalSettingsView.gml create mode 100644 Userland/Applications/TerminalSettings/TerminalSettingsWidget.cpp create mode 100644 Userland/Applications/TerminalSettings/TerminalSettingsWidget.h create mode 100644 Userland/Applications/TerminalSettings/main.cpp diff --git a/Base/res/apps/TerminalSettings.af b/Base/res/apps/TerminalSettings.af new file mode 100644 index 0000000000..53535f3c13 --- /dev/null +++ b/Base/res/apps/TerminalSettings.af @@ -0,0 +1,5 @@ +[App] +Name=Terminal Settings +Executable=/bin/TerminalSettings +Category=Settings +Description=Configure the Terminal appearance and behavior. diff --git a/Userland/Applications/CMakeLists.txt b/Userland/Applications/CMakeLists.txt index a9b4961240..ddd04fe00e 100644 --- a/Userland/Applications/CMakeLists.txt +++ b/Userland/Applications/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(SpaceAnalyzer) add_subdirectory(Spreadsheet) add_subdirectory(SystemMonitor) add_subdirectory(Terminal) +add_subdirectory(TerminalSettings) add_subdirectory(TextEditor) add_subdirectory(ThemeEditor) add_subdirectory(VideoPlayer) diff --git a/Userland/Applications/Terminal/CMakeLists.txt b/Userland/Applications/Terminal/CMakeLists.txt index 37910af321..ea539fe040 100644 --- a/Userland/Applications/Terminal/CMakeLists.txt +++ b/Userland/Applications/Terminal/CMakeLists.txt @@ -4,10 +4,7 @@ serenity_component( TARGETS Terminal utmpupdate ) -compile_gml(TerminalSettingsWindow.gml TerminalSettingsWindowGML.h terminal_settings_window_gml) - set(SOURCES - TerminalSettingsWindowGML.h main.cpp ) diff --git a/Userland/Applications/Terminal/TerminalSettingsWindow.gml b/Userland/Applications/Terminal/TerminalSettingsWindow.gml deleted file mode 100644 index 632bf3e901..0000000000 --- a/Userland/Applications/Terminal/TerminalSettingsWindow.gml +++ /dev/null @@ -1,76 +0,0 @@ -@GUI::Widget { - fill_with_background_color: true - - layout: @GUI::VerticalBoxLayout { - margins: [4] - } - - @GUI::GroupBox { - title: "Bell mode" - shrink_to_fit: true - - layout: @GUI::VerticalBoxLayout { - margins: [4] - } - - @GUI::RadioButton { - name: "beep_bell_radio" - text: "System beep" - } - - @GUI::RadioButton { - name: "visual_bell_radio" - text: "Visual bell" - } - - @GUI::RadioButton { - name: "no_bell_radio" - text: "No bell" - } - } - - @GUI::GroupBox { - title: "Background opacity" - shrink_to_fit: true - - layout: @GUI::VerticalBoxLayout { - margins: [4] - } - - @GUI::OpacitySlider { - name: "background_opacity_slider" - min: 0 - max: 255 - orientation: "Horizontal" - } - } - - @GUI::GroupBox { - title: "Scrollback size (lines)" - shrink_to_fit: true - - layout: @GUI::VerticalBoxLayout { - margins: [4] - } - - @GUI::SpinBox { - name: "history_size_spinbox" - min: 0 - max: 40960 - orientation: "Horizontal" - } - } - - @GUI::GroupBox { - title: "Color scheme" - shrink_to_fit: true - - layout: @GUI::VerticalBoxLayout { - margins: [4] - } - - @GUI::ComboBox { - name: "color_scheme_combo" - } - } -} diff --git a/Userland/Applications/Terminal/main.cpp b/Userland/Applications/Terminal/main.cpp index ae1c0a8711..6fbad746ce 100644 --- a/Userland/Applications/Terminal/main.cpp +++ b/Userland/Applications/Terminal/main.cpp @@ -6,8 +6,8 @@ #include #include -#include #include +#include #include #include #include @@ -21,17 +21,14 @@ #include #include #include -#include #include #include #include #include -#include -#include -#include #include #include #include +#include #include #include #include @@ -47,6 +44,54 @@ #include #include +class TerminalChangeListener : public Config::Listener { +public: + TerminalChangeListener(VT::TerminalWidget& parent_terminal) + : m_parent_terminal(parent_terminal) + { + } + + virtual void config_string_did_change(String const& domain, String const& group, String const& key, String const& value) + { + VERIFY(domain == "Terminal"); + + if (group == "Window") { + if (key == "Bell") { + auto bell_mode = VT::TerminalWidget::BellMode::Visible; + if (value == "AudibleBeep") + bell_mode = VT::TerminalWidget::BellMode::AudibleBeep; + if (value == "Visible") + bell_mode = VT::TerminalWidget::BellMode::Visible; + if (value == "Disabled") + bell_mode = VT::TerminalWidget::BellMode::Disabled; + m_parent_terminal.set_bell_mode(bell_mode); + } else if (key == "ColorScheme") { + m_parent_terminal.set_color_scheme(value); + } + } else if (group == "Text" && key == "Font") { + auto font = Gfx::FontDatabase::the().get_by_name(value); + if (font.is_null()) + font = Gfx::FontDatabase::default_fixed_width_font(); + m_parent_terminal.set_font_and_resize_to_fit(*font); + m_parent_terminal.window()->resize(m_parent_terminal.size()); + } + } + + virtual void config_i32_did_change(String const& domain, String const& group, String const& key, i32 value) + { + VERIFY(domain == "Terminal"); + + if (group == "Terminal" && key == "MaxHistorySize") { + m_parent_terminal.set_max_history_size(value); + } else if (group == "Window" && key == "Opacity") { + m_parent_terminal.set_opacity(value); + } + } + +private: + VT::TerminalWidget& m_parent_terminal; +}; + static void utmp_update(String const& tty, pid_t pid, bool create) { int utmpupdate_pid = fork(); @@ -104,78 +149,6 @@ static void run_command(String command, bool keep_open) VERIFY_NOT_REACHED(); } -static RefPtr create_settings_window(VT::TerminalWidget& terminal) -{ - auto window = GUI::Window::construct(); - window->set_window_type(GUI::WindowType::ToolWindow); - window->set_title("Terminal settings"); - window->set_resizable(false); - window->resize(200, 240); - window->center_within(*terminal.window()); - - auto& settings = window->set_main_widget(); - settings.load_from_gml(terminal_settings_window_gml); - - auto& beep_bell_radio = *settings.find_descendant_of_type_named("beep_bell_radio"); - auto& visual_bell_radio = *settings.find_descendant_of_type_named("visual_bell_radio"); - auto& no_bell_radio = *settings.find_descendant_of_type_named("no_bell_radio"); - - switch (terminal.bell_mode()) { - case VT::TerminalWidget::BellMode::Visible: - visual_bell_radio.set_checked(true); - break; - case VT::TerminalWidget::BellMode::AudibleBeep: - beep_bell_radio.set_checked(true); - break; - case VT::TerminalWidget::BellMode::Disabled: - no_bell_radio.set_checked(true); - break; - } - - beep_bell_radio.on_checked = [&terminal](bool) { - terminal.set_bell_mode(VT::TerminalWidget::BellMode::AudibleBeep); - }; - visual_bell_radio.on_checked = [&terminal](bool) { - terminal.set_bell_mode(VT::TerminalWidget::BellMode::Visible); - }; - no_bell_radio.on_checked = [&terminal](bool) { - terminal.set_bell_mode(VT::TerminalWidget::BellMode::Disabled); - }; - - auto& slider = *settings.find_descendant_of_type_named("background_opacity_slider"); - slider.on_change = [&terminal](int value) { - terminal.set_opacity(value); - }; - slider.set_value(terminal.opacity()); - - auto& history_size_spinbox = *settings.find_descendant_of_type_named("history_size_spinbox"); - history_size_spinbox.set_value(terminal.max_history_size()); - history_size_spinbox.on_change = [&terminal](int value) { - 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 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(); - color_scheme_names.append(path.replace(".ini", "")); - } - quick_sort(color_scheme_names); - auto& color_scheme_combo = *settings.find_descendant_of_type_named("color_scheme_combo"); - color_scheme_combo.set_only_allow_values_from_model(true); - color_scheme_combo.set_model(*GUI::ItemListModel::create(color_scheme_names)); - color_scheme_combo.set_selected_index(color_scheme_names.find_first_index(terminal.color_scheme_name()).value()); - color_scheme_combo.set_enabled(color_scheme_names.size() > 1); - color_scheme_combo.on_change = [&](auto&, const GUI::ModelIndex& index) { - terminal.set_color_scheme(index.data().as_string()); - }; - return window; -} - static ErrorOr> create_find_window(VT::TerminalWidget& terminal) { auto window = TRY(GUI::Window::try_create()); @@ -317,6 +290,9 @@ ErrorOr serenity_main(Main::Arguments arguments) terminal->apply_size_increments_to_window(*window); window->set_icon(app_icon.bitmap_for_size(16)); + Config::monitor_domain("Terminal"); + TerminalChangeListener listener { terminal }; + auto bell = Config::read_string("Terminal", "Window", "Bell", "Visible"); if (bell == "AudibleBeep") { terminal->set_bell_mode(VT::TerminalWidget::BellMode::AudibleBeep); @@ -326,8 +302,6 @@ ErrorOr serenity_main(Main::Arguments arguments) terminal->set_bell_mode(VT::TerminalWidget::BellMode::Visible); } - RefPtr settings_window; - auto find_window = TRY(create_find_window(terminal)); auto new_opacity = Config::read_i32("Terminal", "Window", "Opacity", 255); @@ -338,40 +312,10 @@ ErrorOr serenity_main(Main::Arguments arguments) terminal->set_max_history_size(new_scrollback_size); auto open_settings_action = GUI::Action::create("&Settings", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/settings.png").release_value_but_fixme_should_propagate_errors(), - [&](const GUI::Action&) { - if (!settings_window) - settings_window = create_settings_window(terminal); - settings_window->show(); - settings_window->move_to_front(); - settings_window->on_close = [&]() { - Config::write_i32("Terminal", "Window", "Opacity", terminal->opacity()); - Config::write_i32("Terminal", "Terminal", "MaxHistorySize", terminal->max_history_size()); - - auto bell = terminal->bell_mode(); - auto bell_setting = String::empty(); - if (bell == VT::TerminalWidget::BellMode::AudibleBeep) { - bell_setting = "AudibleBeep"; - } else if (bell == VT::TerminalWidget::BellMode::Disabled) { - bell_setting = "Disabled"; - } else { - bell_setting = "Visible"; - } - Config::write_string("Terminal", "Window", "Bell", bell_setting); - }; - }); - - TRY(terminal->context_menu().try_add_separator()); - auto pick_font_action = GUI::Action::create("&Terminal Font...", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-font-editor.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) { - auto picker = GUI::FontPicker::construct(window, &terminal->font(), true); - if (picker->exec() == GUI::Dialog::ExecOK) { - terminal->set_font_and_resize_to_fit(*picker->font()); - window->resize(terminal->size()); - Config::write_string("Terminal", "Text", "Font", picker->font()->qualified_name()); - } + Core::Process::spawn("/bin/TerminalSettings"); }); - TRY(terminal->context_menu().try_add_action(pick_font_action)); TRY(terminal->context_menu().try_add_separator()); TRY(terminal->context_menu().try_add_action(open_settings_action)); @@ -402,8 +346,6 @@ ErrorOr serenity_main(Main::Arguments arguments) window->set_fullscreen(!window->is_fullscreen()); }))); TRY(view_menu->try_add_action(terminal->clear_including_history_action())); - TRY(view_menu->try_add_separator()); - TRY(view_menu->try_add_action(pick_font_action)); auto help_menu = TRY(window->try_add_menu("&Help")); TRY(help_menu->try_add_action(GUI::CommonActions::make_help_action([](auto&) { @@ -413,13 +355,12 @@ ErrorOr serenity_main(Main::Arguments arguments) window->on_close = [&]() { find_window->close(); - if (settings_window) - settings_window->close(); }; TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/bin", "r")); TRY(Core::System::unveil("/bin/Terminal", "x")); + TRY(Core::System::unveil("/bin/TerminalSettings", "x")); TRY(Core::System::unveil("/bin/utmpupdate", "x")); TRY(Core::System::unveil("/etc/FileIconProvider.ini", "r")); TRY(Core::System::unveil("/tmp/portal/launch", "rw")); diff --git a/Userland/Applications/TerminalSettings/CMakeLists.txt b/Userland/Applications/TerminalSettings/CMakeLists.txt new file mode 100644 index 0000000000..13a82464c3 --- /dev/null +++ b/Userland/Applications/TerminalSettings/CMakeLists.txt @@ -0,0 +1,18 @@ +serenity_component( + TerminalSettings + REQUIRED + TARGETS TerminalSettings +) + +compile_gml(TerminalSettingsMain.gml TerminalSettingsMainGML.h terminal_settings_main_gml) +compile_gml(TerminalSettingsView.gml TerminalSettingsViewGML.h terminal_settings_view_gml) + +set(SOURCES + main.cpp + TerminalSettingsWidget.cpp + TerminalSettingsMainGML.h + TerminalSettingsViewGML.h +) + +serenity_app(TerminalSettings ICON app-terminal) +target_link_libraries(TerminalSettings LibGUI LibConfig) diff --git a/Userland/Applications/TerminalSettings/TerminalSettingsMain.gml b/Userland/Applications/TerminalSettings/TerminalSettingsMain.gml new file mode 100644 index 0000000000..5a44a1f955 --- /dev/null +++ b/Userland/Applications/TerminalSettings/TerminalSettingsMain.gml @@ -0,0 +1,63 @@ +@GUI::Widget { + fill_with_background_color: true + + layout: @GUI::VerticalBoxLayout { + margins: [10] + spacing: 5 + } + + @GUI::GroupBox { + title: "Bell Mode" + shrink_to_fit: false + fixed_height: 160 + + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::Label { + text: "This setting controls the terminal's indication of an ANSI 0x07 bell (\\a)." + text_alignment: "TopLeft" + } + + @GUI::Widget { + shrink_to_fit: true + + layout: @GUI::VerticalBoxLayout { + spacing: 4 + } + + @GUI::RadioButton { + name: "beep_bell_radio" + text: "System beep" + } + + @GUI::RadioButton { + name: "visual_bell_radio" + text: "Visual bell" + } + + @GUI::RadioButton { + name: "no_bell_radio" + text: "No bell" + } + } + } + + @GUI::GroupBox { + title: "Scrollback Size (Lines)" + shrink_to_fit: true + + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + } + + @GUI::SpinBox { + name: "history_size_spinbox" + min: 0 + max: 40960 + orientation: "Horizontal" + } + } +} diff --git a/Userland/Applications/TerminalSettings/TerminalSettingsView.gml b/Userland/Applications/TerminalSettings/TerminalSettingsView.gml new file mode 100644 index 0000000000..39dd69e061 --- /dev/null +++ b/Userland/Applications/TerminalSettings/TerminalSettingsView.gml @@ -0,0 +1,82 @@ +@GUI::Widget { + fill_with_background_color: true + + layout: @GUI::VerticalBoxLayout { + margins: [10] + spacing: 5 + } + + @GUI::GroupBox { + title: "Background Opacity" + fixed_height: 70 + + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::OpacitySlider { + name: "background_opacity_slider" + min: 0 + max: 255 + orientation: "Horizontal" + } + } + + @GUI::GroupBox { + title: "Terminal Font" + fixed_height: 100 + + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::CheckBox { + name: "terminal_font_defaulted" + text: "Use system default" + } + + @GUI::Widget { + shrink_to_fit: true + name: "terminal_font_selection" + + layout: @GUI::HorizontalBoxLayout { + spacing: 6 + } + + @GUI::Frame { + background_role: "Base" + fill_with_background_color: true + + layout: @GUI::VerticalBoxLayout { + } + + @GUI::Label { + name: "terminal_font_label" + text: "Csilla 10 400" + } + } + + @GUI::Button { + text: "..." + name: "terminal_font_button" + fixed_width: 30 + } + } + } + + @GUI::GroupBox { + title: "Color Scheme" + fixed_height: 70 + + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::ComboBox { + name: "color_scheme_combo" + } + } +} diff --git a/Userland/Applications/TerminalSettings/TerminalSettingsWidget.cpp b/Userland/Applications/TerminalSettings/TerminalSettingsWidget.cpp new file mode 100644 index 0000000000..83551f5589 --- /dev/null +++ b/Userland/Applications/TerminalSettings/TerminalSettingsWidget.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2018-2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "TerminalSettingsWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TerminalSettingsMainWidget::TerminalSettingsMainWidget() +{ + load_from_gml(terminal_settings_main_gml); + + auto& beep_bell_radio = *find_descendant_of_type_named("beep_bell_radio"); + auto& visual_bell_radio = *find_descendant_of_type_named("visual_bell_radio"); + auto& no_bell_radio = *find_descendant_of_type_named("no_bell_radio"); + + m_bell_mode = parse_bell(Config::read_string("Terminal", "Window", "Bell")); + m_original_bell_mode = m_bell_mode; + + switch (m_bell_mode) { + case VT::TerminalWidget::BellMode::Visible: + visual_bell_radio.set_checked(true); + break; + case VT::TerminalWidget::BellMode::AudibleBeep: + beep_bell_radio.set_checked(true); + break; + case VT::TerminalWidget::BellMode::Disabled: + no_bell_radio.set_checked(true); + break; + } + + beep_bell_radio.on_checked = [this](bool) { + m_bell_mode = VT::TerminalWidget::BellMode::AudibleBeep; + Config::write_string("Terminal", "Window", "Bell", stringify_bell(m_bell_mode)); + }; + visual_bell_radio.on_checked = [this](bool) { + m_bell_mode = VT::TerminalWidget::BellMode::Visible; + Config::write_string("Terminal", "Window", "Bell", stringify_bell(m_bell_mode)); + }; + no_bell_radio.on_checked = [this](bool) { + m_bell_mode = VT::TerminalWidget::BellMode::Disabled; + Config::write_string("Terminal", "Window", "Bell", stringify_bell(m_bell_mode)); + }; + + m_max_history_size = Config::read_i32("Terminal", "Terminal", "MaxHistorySize"); + m_original_max_history_size = m_max_history_size; + auto& history_size_spinbox = *find_descendant_of_type_named("history_size_spinbox"); + history_size_spinbox.set_value(m_max_history_size); + history_size_spinbox.on_change = [this](int value) { + m_max_history_size = value; + Config::write_i32("Terminal", "Terminal", "MaxHistorySize", static_cast(m_max_history_size)); + }; +} + +TerminalSettingsViewWidget::TerminalSettingsViewWidget() +{ + load_from_gml(terminal_settings_view_gml); + + auto& slider = *find_descendant_of_type_named("background_opacity_slider"); + m_opacity = Config::read_i32("Terminal", "Window", "Opacity"); + m_original_opacity = m_opacity; + slider.set_value(m_opacity); + slider.on_change = [this](int value) { + m_opacity = value; + Config::write_i32("Terminal", "Window", "Opacity", static_cast(m_opacity)); + }; + + m_color_scheme = Config::read_string("Terminal", "Window", "ColorScheme"); + m_original_color_scheme = m_color_scheme; + // 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 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(); + color_scheme_names.append(path.replace(".ini", "")); + } + quick_sort(color_scheme_names); + auto& color_scheme_combo = *find_descendant_of_type_named("color_scheme_combo"); + color_scheme_combo.set_only_allow_values_from_model(true); + color_scheme_combo.set_model(*GUI::ItemListModel::create(color_scheme_names)); + color_scheme_combo.set_selected_index(color_scheme_names.find_first_index(m_color_scheme).value()); + color_scheme_combo.set_enabled(color_scheme_names.size() > 1); + color_scheme_combo.on_change = [&](auto&, const GUI::ModelIndex& index) { + m_color_scheme = index.data().as_string(); + Config::write_string("Terminal", "Window", "ColorScheme", m_color_scheme); + }; + + auto& font_button = *find_descendant_of_type_named("terminal_font_button"); + auto& font_text = *find_descendant_of_type_named("terminal_font_label"); + auto font_name = Config::read_string("Terminal", "Text", "Font"); + if (font_name.is_empty()) + m_font = Gfx::FontDatabase::the().default_fixed_width_font(); + else + m_font = Gfx::FontDatabase::the().get_by_name(font_name); + m_original_font = m_font; + font_text.set_text(m_font->qualified_name()); + font_text.set_font(m_font); + font_button.on_click = [&](auto) { + auto picker = GUI::FontPicker::construct(window(), m_font.ptr(), true); + if (picker->exec() == GUI::Dialog::ExecOK) { + m_font = picker->font(); + font_text.set_text(m_font->qualified_name()); + font_text.set_font(m_font); + Config::write_string("Terminal", "Text", "Font", m_font->qualified_name()); + } + }; + + auto& font_selection = *find_descendant_of_type_named("terminal_font_selection"); + auto& use_default_font_button = *find_descendant_of_type_named("terminal_font_defaulted"); + use_default_font_button.on_checked = [&](bool use_default_font) { + if (use_default_font) { + font_selection.set_enabled(false); + m_font = Gfx::FontDatabase::the().default_fixed_width_font(); + Config::write_string("Terminal", "Text", "Font", m_font->qualified_name()); + } else { + font_selection.set_enabled(true); + m_font = Gfx::FontDatabase::the().get_by_name(font_text.text()); + Config::write_string("Terminal", "Text", "Font", m_font->qualified_name()); + } + }; + // The "use default font" setting is not stored itself - we automatically set it if the actually present font is the default, + // whether that was filled in by the above defaulting code or by the user. + use_default_font_button.set_checked(m_font == Gfx::FontDatabase::the().default_fixed_width_font()); +} + +VT::TerminalWidget::BellMode TerminalSettingsMainWidget::parse_bell(StringView bell_string) +{ + if (bell_string == "AudibleBeep") + return VT::TerminalWidget::BellMode::AudibleBeep; + if (bell_string == "Visible") + return VT::TerminalWidget::BellMode::Visible; + if (bell_string == "Disabled") + return VT::TerminalWidget::BellMode::Disabled; + VERIFY_NOT_REACHED(); +} + +String TerminalSettingsMainWidget::stringify_bell(VT::TerminalWidget::BellMode bell_mode) +{ + if (bell_mode == VT::TerminalWidget::BellMode::AudibleBeep) + return "AudibleBeep"; + if (bell_mode == VT::TerminalWidget::BellMode::Disabled) + return "Disabled"; + if (bell_mode == VT::TerminalWidget::BellMode::Visible) + return "Visible"; + VERIFY_NOT_REACHED(); +} + +void TerminalSettingsMainWidget::apply_settings() +{ + m_original_max_history_size = m_max_history_size; + m_original_bell_mode = m_bell_mode; + write_back_settings(); +} +void TerminalSettingsMainWidget::write_back_settings() const +{ + Config::write_i32("Terminal", "Terminal", "MaxHistorySize", static_cast(m_original_max_history_size)); + Config::write_string("Terminal", "Window", "Bell", stringify_bell(m_original_bell_mode)); +} + +void TerminalSettingsMainWidget::cancel_settings() +{ + write_back_settings(); +} + +void TerminalSettingsViewWidget::apply_settings() +{ + m_original_opacity = m_opacity; + m_original_font = m_font; + m_original_color_scheme = m_color_scheme; + write_back_settings(); +} + +void TerminalSettingsViewWidget::write_back_settings() const +{ + Config::write_i32("Terminal", "Window", "Opacity", static_cast(m_original_opacity)); + Config::write_string("Terminal", "Text", "Font", m_original_font->qualified_name()); + Config::write_string("Terminal", "Window", "ColorScheme", m_original_color_scheme); +} + +void TerminalSettingsViewWidget::cancel_settings() +{ + write_back_settings(); +} diff --git a/Userland/Applications/TerminalSettings/TerminalSettingsWidget.h b/Userland/Applications/TerminalSettings/TerminalSettingsWidget.h new file mode 100644 index 0000000000..4f97f15a7c --- /dev/null +++ b/Userland/Applications/TerminalSettings/TerminalSettingsWidget.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +class TerminalSettingsMainWidget final : public GUI::SettingsWindow::Tab { + C_OBJECT(TerminalSettingsMainWidget) +public: + virtual void apply_settings() override; + virtual void cancel_settings() override; + +private: + TerminalSettingsMainWidget(); + void write_back_settings() const; + + static VT::TerminalWidget::BellMode parse_bell(StringView bell_string); + static String stringify_bell(VT::TerminalWidget::BellMode bell_mode); + + VT::TerminalWidget::BellMode m_bell_mode = VT::TerminalWidget::BellMode::Disabled; + size_t m_max_history_size; + + VT::TerminalWidget::BellMode m_original_bell_mode; + size_t m_original_max_history_size; +}; + +class TerminalSettingsViewWidget final : public GUI::SettingsWindow::Tab { + C_OBJECT(TerminalSettingsViewWidget) +public: + virtual void apply_settings() override; + virtual void cancel_settings() override; + +private: + TerminalSettingsViewWidget(); + void write_back_settings() const; + + RefPtr m_font; + float m_opacity; + String m_color_scheme; + + RefPtr m_original_font; + float m_original_opacity; + String m_original_color_scheme; +}; diff --git a/Userland/Applications/TerminalSettings/main.cpp b/Userland/Applications/TerminalSettings/main.cpp new file mode 100644 index 0000000000..118d534e40 --- /dev/null +++ b/Userland/Applications/TerminalSettings/main.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "TerminalSettingsWidget.h" +#include +#include +#include + +// Including this after to avoid LibIPC errors +#include + +int main(int argc, char** argv) +{ + if (pledge("stdio rpath cpath wpath recvfd sendfd unix proc exec", nullptr) < 0) { + perror("pledge"); + return 1; + } + + auto app = GUI::Application::construct(argc, argv); + Config::pledge_domains("Terminal"); + + if (pledge("stdio rpath cpath wpath recvfd sendfd proc exec", nullptr) < 0) { + perror("pledge"); + return 1; + } + + if (unveil("/res", "r") < 0) { + perror("unveil"); + return 1; + } + + if (unveil("/bin/keymap", "x") < 0) { + perror("unveil"); + return 1; + } + + if (unveil("/proc/keymap", "r") < 0) { + perror("unveil"); + return 1; + } + + if (unveil(nullptr, nullptr)) { + perror("unveil"); + return 1; + } + + auto app_icon = GUI::Icon::default_icon("app-terminal"); + + auto window = GUI::SettingsWindow::construct("Terminal Settings"); + window->set_icon(app_icon.bitmap_for_size(16)); + window->add_tab("Terminal"); + window->add_tab("View"); + + window->show(); + return app->exec(); +}