1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 21:17:45 +00:00

Base+WindowsServer+keymap: Store multiple keymaps in a config

This commit is contained in:
Timur Sultanov 2022-01-19 18:20:42 +03:00 committed by Andreas Kling
parent 5a31697bcf
commit c7bd47c87c
12 changed files with 405 additions and 100 deletions

View file

@ -5,6 +5,7 @@
*/
#include <AK/JsonObject.h>
#include <LibCore/ConfigFile.h>
#include <LibCore/File.h>
#include <WindowServer/KeymapSwitcher.h>
#include <spawn.h>
@ -14,6 +15,15 @@ namespace WindowServer {
KeymapSwitcher::KeymapSwitcher()
{
m_file_watcher = MUST(Core::FileWatcher::create());
m_file_watcher->on_change = [this](auto&) {
refresh();
};
MUST(m_file_watcher->add_watch(m_keyboard_config, Core::FileWatcherEvent::Type::ContentModified));
refresh();
}
KeymapSwitcher::~KeymapSwitcher()
@ -24,15 +34,34 @@ void KeymapSwitcher::refresh()
{
m_keymaps.clear();
//TODO: load keymaps from file
m_keymaps.append("en-us");
m_keymaps.append("ru");
auto mapper_config(Core::ConfigFile::open(m_keyboard_config));
auto keymaps = mapper_config->read_entry("Mapping", "Keymaps", "");
auto keymaps_vector = keymaps.split(',');
for (auto& keymap : keymaps_vector) {
m_keymaps.append(keymap);
}
if (m_keymaps.is_empty()) {
dbgln("Empty list of keymaps - adding default (en-us)");
m_keymaps.append("en-us");
}
auto current_keymap = get_current_keymap();
// Refresh might indicate that some external program has changed the keymap,
// so better notify our clients that we may have a new keymap
if (on_keymap_change)
on_keymap_change(current_keymap);
if (m_keymaps.find(current_keymap).is_end()) {
setkeymap(m_keymaps.first());
}
}
void KeymapSwitcher::next_keymap()
{
refresh();
if (m_keymaps.is_empty()) {
dbgln("No keymaps loaded - leaving system keymap unchanged");
return; // TODO: figure out what to do when there is no keymap configured
@ -77,7 +106,7 @@ String KeymapSwitcher::get_current_keymap() const
void KeymapSwitcher::setkeymap(const AK::String& keymap)
{
pid_t child_pid;
const char* argv[] = { "/bin/keymap", keymap.characters(), nullptr };
const char* argv[] = { "/bin/keymap", "-m", keymap.characters(), nullptr };
if ((errno = posix_spawn(&child_pid, "/bin/keymap", nullptr, nullptr, const_cast<char**>(argv), environ))) {
perror("posix_spawn");
dbgln("Failed to call /bin/keymap, error: {} ({})", errno, strerror(errno));

View file

@ -9,6 +9,7 @@
#include <AK/String.h>
#include <AK/Vector.h>
#include <AK/WeakPtr.h>
#include <LibCore/FileWatcher.h>
#include <LibCore/Object.h>
#include <LibKeyboard/CharacterMap.h>
#include <WindowServer/WMClientConnection.h>
@ -20,8 +21,6 @@ class KeymapSwitcher final : public Core::Object {
public:
virtual ~KeymapSwitcher() override;
void refresh();
void next_keymap();
Function<void(String const& keymap)> on_keymap_change;
@ -29,11 +28,17 @@ public:
String get_current_keymap() const;
private:
void refresh();
KeymapSwitcher();
Vector<AK::String> m_keymaps;
void setkeymap(AK::String const&);
RefPtr<Core::FileWatcher> m_file_watcher;
const char* m_keyboard_config = "/etc/Keyboard.ini";
};
}

View file

@ -25,6 +25,7 @@ ErrorOr<int> serenity_main(Main::Arguments)
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil("/tmp", "cw"));
TRY(Core::System::unveil("/etc/WindowServer.ini", "rwc"));
TRY(Core::System::unveil("/etc/Keyboard.ini", "r"));
TRY(Core::System::unveil("/dev", "rw"));
TRY(Core::System::unveil("/bin/keymap", "x"));
TRY(Core::System::unveil("/proc/keymap", "r"));