ladybird/Userland/Utilities/keymap.cpp
Paweł Łukasik a0ffdeb58a Keymap: Fix switching selected keymap
Previously keymap did switching of the selected keymap twice when the
command was executed. First set it to the first keymap on the list and
later, if present, to the chosen one.

Currently the switching to the first keymap on the list is done only
when the selection is not present or it's not on the list of keymaps.
2022-06-16 14:58:43 +01:00

102 lines
3.2 KiB
C++

/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/ConfigFile.h>
#include <LibCore/System.h>
#include <LibKeyboard/CharacterMap.h>
#include <LibMain/Main.h>
#include <stdio.h>
int set_keymap(String const& keymap);
int set_keymap(String const& keymap)
{
auto character_map = Keyboard::CharacterMap::load_from_file(keymap);
if (character_map.is_error()) {
warnln("Cannot read keymap {}", keymap);
warnln("Hint: Must be a keymap name (e.g. 'en-us')");
return 1;
}
int rc = character_map.value().set_system_map();
if (rc != 0) {
perror("setkeymap");
}
return rc;
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
TRY(Core::System::pledge("stdio setkeymap getkeymap rpath wpath cpath"));
TRY(Core::System::unveil("/res/keymaps", "r"));
TRY(Core::System::unveil("/etc/Keyboard.ini", "rwc"));
String mapping;
String mappings;
Core::ArgsParser args_parser;
args_parser.add_option(mapping, "The mapping to be used", "set-keymap", 'm', "keymap");
args_parser.add_option(mappings, "Comma separated list of enabled mappings", "set-keymaps", 's', "keymaps");
args_parser.parse(arguments);
TRY(Core::System::unveil(nullptr, nullptr));
if (mapping.is_empty() && mappings.is_empty()) {
auto keymap = TRY(Keyboard::CharacterMap::fetch_system_map());
outln("{}", keymap.character_map_name());
return 0;
}
auto mapper_config = TRY(Core::ConfigFile::open("/etc/Keyboard.ini", Core::ConfigFile::AllowWriting::Yes));
if (!mappings.is_empty()) {
auto mappings_vector = mappings.split(',');
if (mappings_vector.is_empty()) {
warnln("Keymaps list should not be empty");
return 1;
}
// Verify that all specified keymaps are loadable
for (auto& keymap_name : mappings_vector) {
auto keymap = Keyboard::CharacterMap::load_from_file(keymap_name);
if (keymap.is_error()) {
warnln("Cannot load keymap {}: {}({})", keymap_name, keymap.error().string_literal(), keymap.error().code());
return keymap.error();
}
}
auto keymaps = String::join(',', mappings_vector);
mapper_config->write_entry("Mapping", "Keymaps", keymaps);
TRY(mapper_config->sync());
}
auto keymaps = mapper_config->read_entry("Mapping", "Keymaps");
auto keymaps_vector = keymaps.split(',');
if (!mapping.is_empty()) {
if (keymaps_vector.is_empty()) {
warnln("No keymaps configured - writing default configurations (en-us)");
mapper_config->write_entry("Mapping", "Keymaps", "en-us");
TRY(mapper_config->sync());
keymaps_vector.append("en-us");
}
if (!keymaps_vector.find(mapping).is_end()) {
int rc = set_keymap(mapping);
if (rc == 0)
return rc;
} else {
warnln("Keymap '{}' is not in list of configured keymaps ({})", mapping, keymaps);
}
}
return set_keymap(keymaps_vector.first());
}