From 6aa26582f63c13e32dd0191015550a2d1eade7e6 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 3 Dec 2022 15:56:07 +0000 Subject: [PATCH] added hyprctl switchxkblayout --- hyprctl/main.cpp | 11 ++++++- src/config/ConfigManager.cpp | 7 ++--- src/debug/HyprCtl.cpp | 47 +++++++++++++++++++++++++++++ src/managers/input/InputManager.cpp | 25 +++++++-------- src/managers/input/InputManager.hpp | 2 ++ src/managers/input/Tablets.cpp | 4 +-- 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 516a3080..0d8dc5d0 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -37,15 +37,23 @@ commands: setcursor getoption cursorpos + switchxkblayout flags: -j -> output in JSON --batch -> execute a batch of commands, separated by ';' )#"; -void request(std::string arg) { +void request(std::string arg, int minArgs = 0) { const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); + const auto ARGS = std::count(arg.begin(), arg.end(), ' '); + + if (ARGS < minArgs) { + std::cout << "Not enough arguments, expected at least " << minArgs; + return; + } + if (SERVERSOCKET < 0) { std::cout << "Couldn't open a socket (1)"; return; @@ -316,6 +324,7 @@ int main(int argc, char** argv) { else if (fullRequest.contains("/reload")) request(fullRequest); else if (fullRequest.contains("/getoption")) request(fullRequest); else if (fullRequest.contains("/cursorpos")) request(fullRequest); + else if (fullRequest.contains("/switchxkblayout")) request(fullRequest, 2); else if (fullRequest.contains("/output")) exitStatus = outputRequest(argc, argv); else if (fullRequest.contains("/setcursor")) exitStatus = setcursorRequest(argc, argv); else if (fullRequest.contains("/dispatch")) exitStatus = dispatchRequest(argc, argv); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 66c22318..fdb227c3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1333,13 +1333,10 @@ SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) { SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) { std::lock_guard lg(configmtx); - auto devcopy = dev; - std::replace(devcopy.begin(), devcopy.end(), ' ', '-'); - - const auto it = deviceConfigs.find(devcopy); + const auto it = deviceConfigs.find(dev); if (it == deviceConfigs.end()) { - Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", devcopy.c_str()); + Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", dev.c_str()); return SConfigValue(); } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 64ffd779..1f0466a2 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -686,6 +686,51 @@ std::string dispatchSetCursor(std::string request) { return "ok"; } +std::string switchXKBLayoutRequest(std::string request) { + CVarList vars(request, 0, ' '); + + const auto KB = vars[1]; + const auto CMD = vars[2]; + + // get kb + const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(), [&] (const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); }); + + if (PKEYBOARD == g_pInputManager->m_lKeyboards.end()) + return "device not found"; + + const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard); + const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap); + xkb_layout_index_t activeLayout = 0; + while (activeLayout < LAYOUTS) { + if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE)) + break; + + activeLayout++; + } + + if (CMD == "next") { + wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1); + } else if (CMD == "prev") { + wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1); + } else { + + int requestedLayout = 0; + try { + requestedLayout = std::stoi(CMD); + } catch (std::exception& e) { + return "invalid arg 2"; + } + + if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) { + return "layout idx out of range of " + std::to_string(LAYOUTS); + } + + wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout); + } + + return "ok"; +} + std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) { std::string curitem = ""; @@ -851,6 +896,8 @@ std::string getReply(std::string request) { return splashRequest(); else if (request == "cursorpos") return cursorPosRequest(format); + else if (request.find("switchxkblayout") == 0) + return switchXKBLayoutRequest(request); else if (request.find("output") == 0) return dispatchOutput(request); else if (request.find("dispatch") == 0) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index bd983c30..691e9323 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -465,7 +465,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) { PNEWKEYBOARD->keyboard = keyboard; try { - PNEWKEYBOARD->name = std::string(keyboard->name); + PNEWKEYBOARD->name = deviceNameToInternalString(keyboard->name); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } @@ -501,7 +501,7 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) { PNEWKEYBOARD->isVirtual = true; try { - PNEWKEYBOARD->name = std::string(keyboard->name); + PNEWKEYBOARD->name = deviceNameToInternalString(keyboard->name); } catch (std::exception& e) { Debug::log(ERR, "Keyboard had no name???"); // logic error } @@ -538,7 +538,6 @@ void CInputManager::setKeyboardLayout() { void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { auto devname = pKeyboard->name; - transform(devname.begin(), devname.end(), devname.begin(), ::tolower); const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); @@ -662,7 +661,7 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) { PMOUSE->mouse = mouse; PMOUSE->virt = virt; try { - PMOUSE->name = std::string(mouse->name); + PMOUSE->name = deviceNameToInternalString(mouse->name); } catch(std::exception& e) { Debug::log(ERR, "Mouse had no name???"); // logic error } @@ -693,7 +692,6 @@ void CInputManager::setPointerConfigs() { const auto PPOINTER = &m; auto devname = PPOINTER->name; - transform(devname.begin(), devname.end(), devname.begin(), ::tolower); const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); @@ -1084,7 +1082,7 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) { PNEWDEV->pWlrDevice = pDevice; try { - PNEWDEV->name = std::string(pDevice->name); + PNEWDEV->name = deviceNameToInternalString(pDevice->name); } catch(std::exception& e) { Debug::log(ERR, "Touch Device had no name???"); // logic error } @@ -1138,18 +1136,15 @@ void CInputManager::setTouchDeviceConfigs() { for (auto& m : m_lTouchDevices) { const auto PTOUCHDEV = &m; - auto devname = PTOUCHDEV->name; - transform(devname.begin(), devname.end(), devname.begin(), ::tolower); - - const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname); + const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PTOUCHDEV->name); if (wlr_input_device_is_libinput(m.pWlrDevice)) { const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.pWlrDevice); - const int ROTATION = std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "touch_transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7); + const int ROTATION = std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "touch_transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7); libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]); - const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "touch_output") : g_pConfigManager->getString("input:touchdevice:output"); + const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(PTOUCHDEV->name, "touch_output") : g_pConfigManager->getString("input:touchdevice:output"); if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY) PTOUCHDEV->boundOutput = OUTPUT; else @@ -1203,3 +1198,9 @@ void CInputManager::unsetCursorImage() { if (!g_pHyprRenderer->m_bWindowRequestedCursorHide) wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor); } + +std::string CInputManager::deviceNameToInternalString(std::string in) { + std::replace(in.begin(), in.end(), ' ', '-'); + std::transform(in.begin(), in.end(), in.begin(), ::tolower); + return in; +} diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 5e3db515..049b1983 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -131,6 +131,8 @@ public: void setCursorImageUntilUnset(std::string); void unsetCursorImage(); + std::string deviceNameToInternalString(std::string); + private: bool m_bCursorImageOverriden = false; diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 5253152e..eef466ec 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -5,7 +5,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { const auto PNEWTABLET = &m_lTablets.emplace_back(); try { - PNEWTABLET->name = std::string(pDevice->name); + PNEWTABLET->name = deviceNameToInternalString(pDevice->name); } catch (std::exception& e) { Debug::log(ERR, "Tablet had no name???"); // logic error } @@ -158,7 +158,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) { const auto PNEWPAD = &m_lTabletPads.emplace_back(); try { - PNEWPAD->name = std::string(pDevice->name); + PNEWPAD->name = deviceNameToInternalString(pDevice->name); } catch (std::exception& e) { Debug::log(ERR, "Pad had no name???"); // logic error }