diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da7cd878..c290a49d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2080,7 +2080,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) } CMonitor* CCompositor::getMonitorFromString(const std::string& name) { - if (name[0] == '+' || name[0] == '-') { + if (name == "current") + return g_pCompositor->m_pLastMonitor; + else if (isDirection(name)) + return getMonitorInDirection(name[0]); + else if (name[0] == '+' || name[0] == '-') { // relative if (m_vMonitors.size() == 1) @@ -2135,33 +2139,15 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); return nullptr; } - } else if (name.starts_with("desc:")) { - const auto DESCRIPTION = name.substr(5); - + } else { for (auto& m : m_vMonitors) { if (!m->output) continue; - if (m->szDescription.starts_with(DESCRIPTION)) { + if (m->matchesStaticSelector(name)) { return m.get(); } } - - return nullptr; - } else { - if (name == "current") - return g_pCompositor->m_pLastMonitor; - - if (isDirection(name)) { - const auto PMONITOR = getMonitorInDirection(name[0]); - return PMONITOR; - } else { - for (auto& m : m_vMonitors) { - if (m->szName == name) { - return m.get(); - } - } - } } return nullptr; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 22475a75..8b14e75a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -465,7 +465,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("input:touchpad:drag_lock", {0L}); m_pConfig->addConfigValue("input:touchpad:scroll_factor", {1.f}); m_pConfig->addConfigValue("input:touchdevice:transform", {0L}); - m_pConfig->addConfigValue("input:touchdevice:output", {STRVAL_EMPTY}); + m_pConfig->addConfigValue("input:touchdevice:output", {"[[Auto]]"}); m_pConfig->addConfigValue("input:touchdevice:enabled", {1L}); m_pConfig->addConfigValue("input:tablet:transform", {0L}); m_pConfig->addConfigValue("input:tablet:output", {STRVAL_EMPTY}); @@ -907,33 +907,21 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s return VAL; } -SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const std::string& displayName) { - SMonitorRule* found = nullptr; - +SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { for (auto& r : m_dMonitorRules) { - if (r.name == name || - (r.name.starts_with("desc:") && - (r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) { - found = &r; - break; + if (PMONITOR.matchesStaticSelector(r.name)) { + return r; } } - if (found) - return *found; - - Debug::log(WARN, "No rule found for {}, trying to use the first.", name); + Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName); for (auto& r : m_dMonitorRules) { if (r.name == "") { - found = &r; - break; + return r; } } - if (found) - return *found; - Debug::log(WARN, "No rules configured. Using the default hardcoded one."); return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-INT32_MAX, -INT32_MAX), .scale = -1}; // 0, 0 is preferred and -1, -1 is auto @@ -1173,7 +1161,7 @@ void CConfigManager::performMonitorReload() { if (!m->output || m->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(m->szName, m->szDescription); + auto rule = getMonitorRuleFor(*m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { overAgain = true; @@ -1230,7 +1218,7 @@ void CConfigManager::ensureMonitorStatus() { if (!rm->output || rm->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(rm->szName, rm->szDescription); + auto rule = getMonitorRuleFor(*rm); if (rule.disabled == rm->m_bEnabled) g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 3784fa91..48131bdd 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -102,7 +102,7 @@ class CConfigManager { static std::string getConfigDir(); static std::string getMainConfigPath(); - SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = ""); + SMonitorRule getMonitorRuleFor(const CMonitor&); SWorkspaceRule getWorkspaceRuleFor(CWorkspace*); std::string getDefaultWorkspaceFor(const std::string&); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index db385902..2dd2a2d9 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -64,7 +64,7 @@ void CMonitor::onConnect(bool noRule) { createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable // get monitor rule that matches - SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : ""); + SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this); // if it's disabled, disable and ignore if (monitorRule.disabled) { @@ -142,6 +142,20 @@ void CMonitor::onConnect(bool noRule) { if (!noRule) g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); + for (const auto& PTOUCHDEV : g_pInputManager->m_lTouchDevices) { + if (matchesStaticSelector(PTOUCHDEV.boundOutput)) { + Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV.name, szName); + wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV.pWlrDevice, output); + } + } + + for (const auto& PTABLET : g_pInputManager->m_lTablets) { + if (matchesStaticSelector(PTABLET.boundOutput)) { + Debug::log(LOG, "Binding tablet {} to output {}", PTABLET.name, szName); + wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTABLET.wlrDevice, output); + } + } + if (!state.commit()) Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit"); @@ -343,6 +357,19 @@ bool CMonitor::isMirror() { return pMirrorOf != nullptr; } +bool CMonitor::matchesStaticSelector(const std::string& selector) const { + if (selector.starts_with("desc:")) { + // match by description + const auto DESCRIPTIONSELECTOR = selector.substr(5); + const auto DESCRIPTION = removeBeginEndSpacesTabs(szDescription.substr(0, szDescription.find_first_of('('))); + + return DESCRIPTIONSELECTOR == szDescription || DESCRIPTIONSELECTOR == DESCRIPTION; + } else { + // match by selector + return szName == selector; + } +} + int CMonitor::findAvailableDefaultWS() { for (size_t i = 1; i < INT32_MAX; ++i) { if (g_pCompositor->getWorkspaceByID(i)) @@ -422,7 +449,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) { pMirrorOf = nullptr; // set rule - const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName, this->output->description ? this->output->description : ""); + const auto RULE = g_pConfigManager->getMonitorRuleFor(*this); vecPosition = RULE.offset; diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 67883e55..051c5305 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -140,6 +140,7 @@ class CMonitor { void addDamage(const CBox* box); void setMirror(const std::string&); bool isMirror(); + bool matchesStaticSelector(const std::string& selector) const; float getDefaultScale(); void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index be0fd005..8cfee18a 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -259,6 +259,8 @@ struct STablet { std::string name = ""; + std::string boundOutput = ""; + // bool operator==(const STablet& b) const { return wlrDevice == b.wlrDevice; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a74e880d..85598f20 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1632,7 +1632,7 @@ void CKeybindManager::forceRendererReload(std::string args) { if (!m->output) continue; - auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->szDescription); + auto rule = g_pConfigManager->getMonitorRuleFor(*m); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { overAgain = true; break; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 81342b67..bda23378 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1491,14 +1491,27 @@ void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) { libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode); const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7); + Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->name); if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV)) libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]); - const auto OUTPUT = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output"); - if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY) - PTOUCHDEV->boundOutput = OUTPUT; - else - PTOUCHDEV->boundOutput = ""; + auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output"); + bool bound = !output.empty() && output != STRVAL_EMPTY; + const bool AUTODETECT = output == "[[Auto]]"; + if (!bound && AUTODETECT) { + const auto DEFAULTOUTPUT = wlr_touch_from_input_device(PTOUCHDEV->pWlrDevice)->output_name; + if (DEFAULTOUTPUT) { + output = DEFAULTOUTPUT; + bound = true; + } + } + PTOUCHDEV->boundOutput = bound ? output : ""; + const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr; + if (PMONITOR) { + Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->name, PMONITOR->szName); + wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV->pWlrDevice, PMONITOR->output); + } else if (bound) + Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->name, output); } }; @@ -1529,9 +1542,12 @@ void CInputManager::setTabletConfigs() { const auto OUTPUT = g_pConfigManager->getDeviceString(t.name, "output", "input:tablet:output"); const auto PMONITOR = g_pCompositor->getMonitorFromString(OUTPUT); if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY && PMONITOR) { + Debug::log(LOG, "Binding tablet {} to output {}", t.name, PMONITOR->szName); wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output); wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr); - } + t.boundOutput = OUTPUT; + } else if (!PMONITOR) + Debug::log(ERR, "Failed to bind tablet {} to output '{}': monitor not found", t.name, OUTPUT); const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position"); const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size");