hyprctl: add an active layout index field in devices (#11531)

This commit is contained in:
Levizor 2025-09-09 15:19:51 +02:00 committed by GitHub
parent ecc9e4d8cd
commit 150d693fe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 23 deletions

View file

@ -1,7 +1,9 @@
#include "tests.hpp" #include "tests.hpp"
#include "../../shared.hpp" #include "../../shared.hpp"
#include "../../hyprctlCompat.hpp" #include "../../hyprctlCompat.hpp"
#include <cstdint>
#include <print> #include <print>
#include <string>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <hyprutils/os/Process.hpp> #include <hyprutils/os/Process.hpp>
@ -29,6 +31,24 @@ static std::string getCommandStdOut(std::string command) {
return stdOut.substr(0, stdOut.length() - 1); 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() { static bool testGetprop() {
NLog::log("{}Testing hyprctl getprop", Colors::GREEN); NLog::log("{}Testing hyprctl getprop", Colors::GREEN);
if (!Tests::spawnKitty()) { if (!Tests::spawnKitty()) {
@ -154,8 +174,9 @@ static bool test() {
EXPECT(jqProc.exitCode(), 0); EXPECT(jqProc.exitCode(), 0);
} }
if (!testGetprop()) testGetprop();
return false; testDevicesActiveLayoutIndex();
getFromSocket("/reload");
return !ret; return !ret;
} }

View file

@ -734,7 +734,9 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque
result += "\"keyboards\": [\n"; result += "\"keyboards\": [\n";
for (auto const& k : g_pInputManager->m_keyboards) { 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( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@ -744,13 +746,14 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque
"layout": "{}", "layout": "{}",
"variant": "{}", "variant": "{}",
"options": "{}", "options": "{}",
"active_layout_index": {},
"active_keymap": "{}", "active_keymap": "{}",
"capsLock": {}, "capsLock": {},
"numLock": {}, "numLock": {},
"main": {} "main": {}
}},)#", }},)#",
rc<uintptr_t>(k.get()), escapeJSONStrings(k->m_hlName), escapeJSONStrings(k->m_currentRules.rules), escapeJSONStrings(k->m_currentRules.model), rc<uintptr_t>(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")); (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"; result += "\n\nKeyboards:\n";
for (auto const& k : g_pInputManager->m_keyboards) { for (auto const& k : g_pInputManager->m_keyboards) {
const auto KM = k->getActiveLayout(); const auto INDEX_OPT = k->getActiveLayoutIndex();
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 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", "{}\n\t\t\tnumLock: {}\n\t\t\tmain: {}\n",
rc<uintptr_t>(k.get()), k->m_hlName, k->m_currentRules.rules, k->m_currentRules.model, k->m_currentRules.layout, k->m_currentRules.variant, rc<uintptr_t>(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")); (k->m_active ? "yes" : "no"));
} }

View file

@ -266,6 +266,19 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
xkb_context_unref(PCONTEXT); xkb_context_unref(PCONTEXT);
} }
std::optional<xkb_layout_index_t> 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() { std::string IKeyboard::getActiveLayout() {
const auto KEYMAP = m_xkbKeymap; const auto KEYMAP = m_xkbKeymap;
const auto STATE = m_xkbState; const auto STATE = m_xkbState;

View file

@ -65,23 +65,24 @@ class IKeyboard : public IHID {
std::string rules = ""; std::string rules = "";
}; };
void setKeymap(const SStringRuleNames& rules); void setKeymap(const SStringRuleNames& rules);
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
std::string getActiveLayout(); std::optional<xkb_layout_index_t> getActiveLayoutIndex();
std::optional<uint32_t> getLEDs(); std::string getActiveLayout();
void updateLEDs(); std::optional<uint32_t> getLEDs();
void updateLEDs(uint32_t leds); void updateLEDs();
uint32_t getModifiers(); void updateLEDs(uint32_t leds);
void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); uint32_t getModifiers();
bool updateModifiersState(); // rets whether changed void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); bool updateModifiersState(); // rets whether changed
void updateKeymapFD(); void updateXkbStateWithKey(uint32_t xkbKey, bool pressed);
bool getPressed(uint32_t key); void updateKeymapFD();
bool shareStates(); bool getPressed(uint32_t key);
bool shareStates();
bool m_active = false; bool m_active = false;
bool m_enabled = true; bool m_enabled = true;
bool m_allowBinds = true; bool m_allowBinds = true;
// permission flag: whether this keyboard is allowed to be processed // permission flag: whether this keyboard is allowed to be processed
bool m_allowed = true; bool m_allowed = true;