diff --git a/hyprtester/src/tests/main/hyprctl.cpp b/hyprtester/src/tests/main/hyprctl.cpp index 2946c6305..95f7caaef 100644 --- a/hyprtester/src/tests/main/hyprctl.cpp +++ b/hyprtester/src/tests/main/hyprctl.cpp @@ -1,7 +1,9 @@ #include "tests.hpp" #include "../../shared.hpp" #include "../../hyprctlCompat.hpp" +#include #include +#include #include #include #include @@ -29,6 +31,24 @@ static std::string getCommandStdOut(std::string command) { return stdOut.substr(0, stdOut.length() - 1); } +static bool testDevicesActiveLayoutIndex() { + NLog::log("{}Testing hyprctl devices active_layout_index", Colors::GREEN); + + // configure layouts + getFromSocket("/keyword input:kb_layout us,pl,ua"); + + for (uint8_t i = 0; i < 3; i++) { + // set layout + getFromSocket("/switchxkblayout all " + std::to_string(i)); + std::string devicesJson = getFromSocket("j/devices"); + std::string expected = R"("active_layout_index": )" + std::to_string(i); + // check layout index + EXPECT_CONTAINS(devicesJson, expected); + } + + return true; +} + static bool testGetprop() { NLog::log("{}Testing hyprctl getprop", Colors::GREEN); if (!Tests::spawnKitty()) { @@ -154,8 +174,9 @@ static bool test() { EXPECT(jqProc.exitCode(), 0); } - if (!testGetprop()) - return false; + testGetprop(); + testDevicesActiveLayoutIndex(); + getFromSocket("/reload"); return !ret; } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 8598b1f6b..c742fec05 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -734,7 +734,9 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque result += "\"keyboards\": [\n"; for (auto const& k : g_pInputManager->m_keyboards) { - const auto KM = k->getActiveLayout(); + const auto INDEX_OPT = k->getActiveLayoutIndex(); + const auto KI = INDEX_OPT.has_value() ? std::to_string(INDEX_OPT.value()) : "none"; + const auto KM = k->getActiveLayout(); result += std::format( R"#( {{ "address": "0x{:x}", @@ -744,13 +746,14 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque "layout": "{}", "variant": "{}", "options": "{}", + "active_layout_index": {}, "active_keymap": "{}", "capsLock": {}, "numLock": {}, "main": {} }},)#", rc(k.get()), escapeJSONStrings(k->m_hlName), escapeJSONStrings(k->m_currentRules.rules), escapeJSONStrings(k->m_currentRules.model), - escapeJSONStrings(k->m_currentRules.layout), escapeJSONStrings(k->m_currentRules.variant), escapeJSONStrings(k->m_currentRules.options), escapeJSONStrings(KM), + escapeJSONStrings(k->m_currentRules.layout), escapeJSONStrings(k->m_currentRules.variant), escapeJSONStrings(k->m_currentRules.options), KI, escapeJSONStrings(KM), (getModState(k, XKB_MOD_NAME_CAPS) ? "true" : "false"), (getModState(k, XKB_MOD_NAME_NUM) ? "true" : "false"), (k->m_active ? "true" : "false")); } @@ -835,11 +838,14 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque result += "\n\nKeyboards:\n"; for (auto const& k : g_pInputManager->m_keyboards) { - const auto KM = k->getActiveLayout(); - result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tcapsLock: " + const auto INDEX_OPT = k->getActiveLayoutIndex(); + const auto KI = INDEX_OPT.has_value() ? std::to_string(INDEX_OPT.value()) : "none"; + const auto KM = k->getActiveLayout(); + result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive layout index: {}\n\t\t\tactive keymap: " + "{}\n\t\t\tcapsLock: " "{}\n\t\t\tnumLock: {}\n\t\t\tmain: {}\n", rc(k.get()), k->m_hlName, k->m_currentRules.rules, k->m_currentRules.model, k->m_currentRules.layout, k->m_currentRules.variant, - k->m_currentRules.options, KM, (getModState(k, XKB_MOD_NAME_CAPS) ? "yes" : "no"), (getModState(k, XKB_MOD_NAME_NUM) ? "yes" : "no"), + k->m_currentRules.options, KI, KM, (getModState(k, XKB_MOD_NAME_CAPS) ? "yes" : "no"), (getModState(k, XKB_MOD_NAME_NUM) ? "yes" : "no"), (k->m_active ? "yes" : "no")); } diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 4f2281b7f..ad9e40d8c 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -266,6 +266,19 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { xkb_context_unref(PCONTEXT); } +std::optional IKeyboard::getActiveLayoutIndex() { + const auto KEYMAP = m_xkbKeymap; + const auto STATE = m_xkbState; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); + + for (xkb_layout_index_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE) == 1) + return i; + } + + return {}; +} + std::string IKeyboard::getActiveLayout() { const auto KEYMAP = m_xkbKeymap; const auto STATE = m_xkbState; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index f4fb667b4..c78325484 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -65,23 +65,24 @@ class IKeyboard : public IHID { std::string rules = ""; }; - void setKeymap(const SStringRuleNames& rules); - void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); - std::string getActiveLayout(); - std::optional getLEDs(); - void updateLEDs(); - void updateLEDs(uint32_t leds); - uint32_t getModifiers(); - void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - bool updateModifiersState(); // rets whether changed - void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); - void updateKeymapFD(); - bool getPressed(uint32_t key); - bool shareStates(); + void setKeymap(const SStringRuleNames& rules); + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + std::optional getActiveLayoutIndex(); + std::string getActiveLayout(); + std::optional getLEDs(); + void updateLEDs(); + void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); + void updateKeymapFD(); + bool getPressed(uint32_t key); + bool shareStates(); - bool m_active = false; - bool m_enabled = true; - bool m_allowBinds = true; + bool m_active = false; + bool m_enabled = true; + bool m_allowBinds = true; // permission flag: whether this keyboard is allowed to be processed bool m_allowed = true;