summaryrefslogtreecommitdiff
path: root/Userland/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Utilities')
-rw-r--r--Userland/Utilities/keymap.cpp94
1 files changed, 74 insertions, 20 deletions
diff --git a/Userland/Utilities/keymap.cpp b/Userland/Utilities/keymap.cpp
index d92977684a..0818798109 100644
--- a/Userland/Utilities/keymap.cpp
+++ b/Userland/Utilities/keymap.cpp
@@ -4,6 +4,8 @@
* 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>
@@ -11,44 +13,96 @@
#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"));
- const char* path = nullptr;
+ String mapping;
+ String mappings;
Core::ArgsParser args_parser;
- args_parser.add_positional_argument(path, "The mapping file to be used", "file", Core::ArgsParser::Required::No);
+ 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);
- if (path && path[0] == '/')
- TRY(Core::System::unveil(path, "r"));
-
TRY(Core::System::unveil(nullptr, nullptr));
- if (!path) {
+ if (mapping.is_empty() && mappings.is_empty()) {
auto keymap = TRY(Keyboard::CharacterMap::fetch_system_map());
outln("{}", keymap.character_map_name());
return 0;
}
- auto character_map = Keyboard::CharacterMap::load_from_file(path);
- if (character_map.is_error()) {
- warnln("Cannot read keymap {}", path);
- warnln("Hint: Must be either a keymap name (e.g. 'en-us') or a full path.");
- return 1;
- }
+ auto mapper_config(Core::ConfigFile::open("/etc/Keyboard.ini", Core::ConfigFile::AllowWriting::Yes));
- int rc = character_map.value().set_system_map();
- if (rc != 0) {
- perror("setkeymap");
- return rc;
+ int rc = 0;
+
+ 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);
+ mapper_config->sync();
+ rc = set_keymap(mappings_vector.first());
+ if (rc != 0) {
+ return rc;
+ }
}
- auto mapper_config(Core::ConfigFile::open("/etc/Keyboard.ini", Core::ConfigFile::AllowWriting::Yes));
- mapper_config->write_entry("Mapping", "Keymap", path);
- mapper_config->sync();
+ auto keymaps = mapper_config->read_entry("Mapping", "Keymaps");
+ auto keymaps_vector = keymaps.split(',');
- return rc;
+ 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");
+ mapper_config->sync();
+ keymaps_vector.append("en-us");
+ }
+
+ if (!keymaps_vector.find(mapping).is_end()) {
+ rc = set_keymap(mapping);
+ if (rc != 0) {
+ return rc;
+ }
+ } else {
+ warnln("Keymap '{}' is not in list of configured keymaps ({})", mapping, keymaps);
+ }
+ }
+
+ return 0;
}