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.
This commit is contained in:
Sam Atkins 2021-11-20 15:49:18 +00:00 committed by Linus Groh
parent 0a2b6b64c6
commit c6099eca5c
Notes: sideshowbarker 2024-07-18 00:58:02 +09:00
3 changed files with 59 additions and 8 deletions

View file

@ -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 {

View file

@ -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<String>::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<GUI::TextEditor>("test_typing_area");
m_clear_test_typing_area_button = find_descendant_of_type_named<GUI::Button>("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<GUI::CheckBox>("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<char**>(argv), environ))) {
perror("posix_spawn");
exit(1);
}
Config::write_bool("KeyboardSettings", "StartupEnable", "NumLock", m_num_lock_checkbox->is_checked());
}

View file

@ -6,22 +6,29 @@
#pragma once
#include <LibGUI/Button.h>
#include <LibGUI/CheckBox.h>
#include <LibGUI/ComboBox.h>
#include <LibGUI/SettingsWindow.h>
#include <LibGUI/TextEditor.h>
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<String> m_character_map_files;
RefPtr<GUI::ComboBox> m_character_map_file_combo;
RefPtr<GUI::TextEditor> m_test_typing_area;
RefPtr<GUI::Button> m_clear_test_typing_area_button;
RefPtr<GUI::CheckBox> m_num_lock_checkbox;
};