KeymapSwitcher.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Copyright (c) 2021, Timur Sultanov <SultanovTS@yandex.ru>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/JsonObject.h>
  7. #include <LibCore/File.h>
  8. #include <WindowServer/KeymapSwitcher.h>
  9. #include <spawn.h>
  10. #include <unistd.h>
  11. namespace WindowServer {
  12. KeymapSwitcher::KeymapSwitcher()
  13. {
  14. }
  15. KeymapSwitcher::~KeymapSwitcher()
  16. {
  17. }
  18. void KeymapSwitcher::refresh()
  19. {
  20. m_keymaps.clear();
  21. //TODO: load keymaps from file
  22. m_keymaps.append("en-us");
  23. m_keymaps.append("ru");
  24. }
  25. void KeymapSwitcher::next_keymap()
  26. {
  27. refresh();
  28. if (m_keymaps.is_empty()) {
  29. dbgln("No keymaps loaded - leaving system keymap unchanged");
  30. return; // TODO: figure out what to do when there is no keymap configured
  31. }
  32. auto current_keymap_name = get_current_keymap();
  33. dbgln("Current system keymap: {}", current_keymap_name);
  34. auto it = m_keymaps.find_if([&](const auto& enumerator) {
  35. return enumerator == current_keymap_name;
  36. });
  37. if (it.is_end()) {
  38. auto first_keymap = m_keymaps.first();
  39. dbgln("Cannot find current keymap in the keymap list - setting first available ({})", first_keymap);
  40. setkeymap(first_keymap);
  41. } else {
  42. it++;
  43. if (it.is_end()) {
  44. it = m_keymaps.begin();
  45. }
  46. dbgln("Setting system keymap to: {}", *it);
  47. setkeymap(*it);
  48. }
  49. }
  50. String KeymapSwitcher::get_current_keymap() const
  51. {
  52. auto proc_keymap = Core::File::construct("/proc/keymap");
  53. if (!proc_keymap->open(Core::OpenMode::ReadOnly))
  54. VERIFY_NOT_REACHED();
  55. auto json = JsonValue::from_string(proc_keymap->read_all()).release_value_but_fixme_should_propagate_errors();
  56. auto const& keymap_object = json.as_object();
  57. VERIFY(keymap_object.has("keymap"));
  58. return keymap_object.get("keymap").to_string();
  59. }
  60. void KeymapSwitcher::setkeymap(const AK::String& keymap)
  61. {
  62. pid_t child_pid;
  63. const char* argv[] = { "/bin/keymap", keymap.characters(), nullptr };
  64. if ((errno = posix_spawn(&child_pid, "/bin/keymap", nullptr, nullptr, const_cast<char**>(argv), environ))) {
  65. perror("posix_spawn");
  66. dbgln("Failed to call /bin/keymap, error: {} ({})", errno, strerror(errno));
  67. }
  68. if (on_keymap_change)
  69. on_keymap_change(keymap);
  70. }
  71. }