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(); +}