From c6099eca5ce609175e3ce113c87405ba2486e9b4 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sat, 20 Nov 2021 15:49:18 +0000 Subject: [PATCH] KeyboardSettings: Add text area to test the currently selected keymap Right now, this is a bit of a hack. We can't set a keymap to only apply to the test area, so we set the system keymap instead, while also keeping track of the "real" current keymap. Whenever the settings are applied, we update what that "real" keymap is, and when we exit, we revert to that keymap. Basically, it behaves as you would expect, apart from it also affecting other applications you are typing in while the KeyboardSettings window is open with a different keymap selected. --- .../KeyboardSettings/Keyboard.gml | 23 +++++++++++- .../KeyboardSettingsWidget.cpp | 35 +++++++++++++++---- .../KeyboardSettings/KeyboardSettingsWidget.h | 9 ++++- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/Userland/Applications/KeyboardSettings/Keyboard.gml b/Userland/Applications/KeyboardSettings/Keyboard.gml index 0e09cb125c..2b17df82c0 100644 --- a/Userland/Applications/KeyboardSettings/Keyboard.gml +++ b/Userland/Applications/KeyboardSettings/Keyboard.gml @@ -8,7 +8,7 @@ @GUI::GroupBox { title: "Mapping" - fixed_height: 60 + fixed_height: 200 layout: @GUI::VerticalBoxLayout { margins: [16, 8, 8] @@ -30,6 +30,27 @@ name: "character_map_file_combo" } } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 16 + } + + @GUI::Label { + text: "Test your current keymap below" + text_alignment: "CenterLeft" + } + @GUI::Button { + text: "Clear" + name: "button_clear_test_typing_area" + fixed_width: 48 + } + } + + @GUI::TextEditor { + fixed_height: 100 + name: "test_typing_area" + } } @GUI::GroupBox { diff --git a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp index 48c92591f0..2fb7e54b90 100644 --- a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp +++ b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.cpp @@ -29,8 +29,8 @@ KeyboardSettingsWidget::KeyboardSettingsWidget() auto json = JsonValue::from_string(proc_keymap->read_all()).release_value_but_fixme_should_propagate_errors(); auto const& keymap_object = json.as_object(); VERIFY(keymap_object.has("keymap")); - String current_keymap = keymap_object.get("keymap").to_string(); - dbgln("KeyboardSettings thinks the current keymap is: {}", current_keymap); + m_current_applied_keymap = keymap_object.get("keymap").to_string(); + dbgln("KeyboardSettings thinks the current keymap is: {}", m_current_applied_keymap); Core::DirIterator iterator("/res/keymaps/", Core::DirIterator::Flags::SkipDots); if (iterator.has_error()) { @@ -46,7 +46,7 @@ KeyboardSettingsWidget::KeyboardSettingsWidget() size_t initial_keymap_index = SIZE_MAX; for (size_t i = 0; i < m_character_map_files.size(); ++i) { - if (m_character_map_files[i].equals_ignoring_case(current_keymap)) + if (m_character_map_files[i].equals_ignoring_case(m_current_applied_keymap)) initial_keymap_index = i; } VERIFY(initial_keymap_index < m_character_map_files.size()); @@ -55,11 +55,29 @@ KeyboardSettingsWidget::KeyboardSettingsWidget() m_character_map_file_combo->set_only_allow_values_from_model(true); m_character_map_file_combo->set_model(*GUI::ItemListModel::create(m_character_map_files)); m_character_map_file_combo->set_selected_index(initial_keymap_index); + // This is a bit of a hack. We set the keymap to the selected one, so that it applies in the testing box below. + // But, we also keep track of the current "applied" keymap, and then revert to that when we exit. + // Ideally, we'd only use the selected keymap for the testing box without making a global system change. + m_character_map_file_combo->on_change = [this](auto& keymap, auto) { + set_keymap(keymap); + }; + + m_test_typing_area = find_descendant_of_type_named("test_typing_area"); + m_clear_test_typing_area_button = find_descendant_of_type_named("button_clear_test_typing_area"); + m_clear_test_typing_area_button->on_click = [this](auto) { + m_test_typing_area->clear(); + m_test_typing_area->set_focus(true); + }; m_num_lock_checkbox = find_descendant_of_type_named("num_lock_checkbox"); m_num_lock_checkbox->set_checked(Config::read_bool("KeyboardSettings", "StartupEnable", "NumLock", true)); } +KeyboardSettingsWidget::~KeyboardSettingsWidget() +{ + set_keymap(m_current_applied_keymap); +} + void KeyboardSettingsWidget::apply_settings() { String character_map_file = m_character_map_file_combo->text(); @@ -67,12 +85,17 @@ void KeyboardSettingsWidget::apply_settings() GUI::MessageBox::show(window(), "Please select character mapping file.", "Keyboard settings", GUI::MessageBox::Type::Error); return; } + m_current_applied_keymap = character_map_file; + set_keymap(character_map_file); + Config::write_bool("KeyboardSettings", "StartupEnable", "NumLock", m_num_lock_checkbox->is_checked()); +} + +void KeyboardSettingsWidget::set_keymap(String const& keymap_filename) +{ pid_t child_pid; - const char* argv[] = { "/bin/keymap", character_map_file.characters(), nullptr }; + const char* argv[] = { "/bin/keymap", keymap_filename.characters(), nullptr }; if ((errno = posix_spawn(&child_pid, "/bin/keymap", nullptr, nullptr, const_cast(argv), environ))) { perror("posix_spawn"); exit(1); } - - Config::write_bool("KeyboardSettings", "StartupEnable", "NumLock", m_num_lock_checkbox->is_checked()); } diff --git a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h index 44129dc37f..9084027354 100644 --- a/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h +++ b/Userland/Applications/KeyboardSettings/KeyboardSettingsWidget.h @@ -6,22 +6,29 @@ #pragma once +#include #include #include #include +#include class KeyboardSettingsWidget final : public GUI::SettingsWindow::Tab { C_OBJECT(KeyboardSettingsWidget) public: - virtual ~KeyboardSettingsWidget() override = default; + virtual ~KeyboardSettingsWidget() override; virtual void apply_settings() override; private: KeyboardSettingsWidget(); + void set_keymap(String const& keymap_filename); + + String m_current_applied_keymap; Vector m_character_map_files; RefPtr m_character_map_file_combo; + RefPtr m_test_typing_area; + RefPtr m_clear_test_typing_area_button; RefPtr m_num_lock_checkbox; };