mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-07 21:05:58 +01:00
input: Map touch devices and tablets bound to an output (#3544)
* Map bound touch devices and tablets to an output * Add "[[Auto]]" default option for auto detecting outputs for touch inputs * Bind new monitors to configured touch and tablet devices * Use Monitor::matchesStaticSelector in CConfigManager::getMonitorRuleFor * Use Monitor::matchesStaticSelector in CCompositor::getMonitorFromString
This commit is contained in:
parent
98034fea3c
commit
60f81b8a23
8 changed files with 71 additions and 51 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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&);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -259,6 +259,8 @@ struct STablet {
|
|||
|
||||
std::string name = "";
|
||||
|
||||
std::string boundOutput = "";
|
||||
|
||||
//
|
||||
bool operator==(const STablet& b) const {
|
||||
return wlrDevice == b.wlrDevice;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue