diff --git a/Userland/Applications/KeyboardSettings/Keyboard.gml b/Userland/Applications/KeyboardSettings/Keyboard.gml index 89ee28391d..a1b5588678 100644 --- a/Userland/Applications/KeyboardSettings/Keyboard.gml +++ b/Userland/Applications/KeyboardSettings/Keyboard.gml @@ -124,4 +124,18 @@ name: "num_lock_checkbox" } } + + @GUI::GroupBox { + title: "Caps Lock" + fixed_height: 60 + layout: @GUI::HorizontalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::CheckBox { + text: "Use Caps Lock as an additional Ctrl" + name: "caps_lock_remapped_to_ctrl_checkbox" + } + } } diff --git a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp index 842018a569..eb97fa661f 100644 --- a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp +++ b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2020, Hüseyin Aslıtürk * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2022, Sam Cohen * Copyright (c) 2022, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause @@ -255,6 +256,19 @@ KeyboardSettingsWidget::KeyboardSettingsWidget() m_num_lock_checkbox->on_checked = [&](auto) { set_modified(true); }; + + m_caps_lock_checkbox = find_descendant_of_type_named("caps_lock_remapped_to_ctrl_checkbox"); + auto caps_lock_is_remapped = read_caps_lock_to_ctrl_sys_variable(); + if (caps_lock_is_remapped.is_error()) { + auto error_message = DeprecatedString::formatted("Could not determine if Caps Lock is remapped to Ctrl: {}", caps_lock_is_remapped.error()); + GUI::MessageBox::show_error(window(), error_message); + } else { + m_caps_lock_checkbox->set_checked(caps_lock_is_remapped.value()); + } + m_caps_lock_checkbox->set_enabled(getuid() == 0); + m_caps_lock_checkbox->on_checked = [&](auto) { + set_modified(true); + }; } KeyboardSettingsWidget::~KeyboardSettingsWidget() @@ -282,6 +296,7 @@ void KeyboardSettingsWidget::apply_settings() } m_initial_active_keymap = m_keymaps_list_model.active_keymap(); Config::write_bool("KeyboardSettings"sv, "StartupEnable"sv, "NumLock"sv, m_num_lock_checkbox->is_checked()); + write_caps_lock_to_ctrl_sys_variable(m_caps_lock_checkbox->is_checked()); } void KeyboardSettingsWidget::set_keymaps(Vector const& keymaps, DeprecatedString const& active_keymap) @@ -289,3 +304,20 @@ void KeyboardSettingsWidget::set_keymaps(Vector const& keymaps auto keymaps_string = DeprecatedString::join(',', keymaps); GUI::Process::spawn_or_show_error(window(), "/bin/keymap"sv, Array { "-s", keymaps_string.characters(), "-m", active_keymap.characters() }); } + +void KeyboardSettingsWidget::write_caps_lock_to_ctrl_sys_variable(bool caps_lock_to_ctrl) +{ + if (getuid() != 0) + return; + + auto write_command = DeprecatedString::formatted("caps_lock_to_ctrl={}", caps_lock_to_ctrl ? "1" : "0"); + GUI::Process::spawn_or_show_error(window(), "/bin/sysctl"sv, Array { "-w", write_command.characters() }); +} + +ErrorOr KeyboardSettingsWidget::read_caps_lock_to_ctrl_sys_variable() +{ + auto file = TRY(Core::File::open("/sys/kernel/variables/caps_lock_to_ctrl"sv, Core::File::OpenMode::Read)); + auto buffer = TRY(file->read_until_eof()); + StringView contents_string((char const*)buffer.data(), min(1, buffer.size())); + return contents_string == "1"; +} diff --git a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h index ff2dba31b9..25720b49d7 100644 --- a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h +++ b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -28,6 +29,9 @@ private: void set_keymaps(Vector const& keymaps, DeprecatedString const& active_keymap); + void write_caps_lock_to_ctrl_sys_variable(bool); + ErrorOr read_caps_lock_to_ctrl_sys_variable(); + Vector m_initial_keymap_list; DeprecatedString m_initial_active_keymap; @@ -35,6 +39,7 @@ private: RefPtr m_selected_keymaps_listview; RefPtr m_active_keymap_label; RefPtr m_num_lock_checkbox; + RefPtr m_caps_lock_checkbox; RefPtr m_activate_keymap_button; RefPtr m_add_keymap_button; RefPtr m_remove_keymap_button; diff --git a/Userland/Applications/KeyboardSettings/main.cpp b/Userland/Applications/KeyboardSettings/main.cpp index 3d8fcb491e..b34c2ba13d 100644 --- a/Userland/Applications/KeyboardSettings/main.cpp +++ b/Userland/Applications/KeyboardSettings/main.cpp @@ -27,7 +27,9 @@ ErrorOr serenity_main(Main::Arguments arguments) TRY(Core::System::pledge("stdio rpath recvfd sendfd proc exec")); TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/bin/keymap", "x")); + TRY(Core::System::unveil("/bin/sysctl", "x")); TRY(Core::System::unveil("/sys/kernel/keymap", "r")); + TRY(Core::System::unveil("/sys/kernel/variables/caps_lock_to_ctrl", "r")); TRY(Core::System::unveil("/etc/Keyboard.ini", "r")); TRY(Core::System::unveil(nullptr, nullptr));