Skip to content

Commit

Permalink
improve output config
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Aug 29, 2024
1 parent b9b8e62 commit 2ab4ae5
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 77 deletions.
63 changes: 51 additions & 12 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "config/ConfigValue.hpp"
#include "helpers/varlist/VarList.hpp"
#include "../protocols/LayerShell.hpp"
#include "../protocols/OutputManagement.hpp"

#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -1033,28 +1034,66 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s
return VAL;
}

SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
SMonitorRule CConfigManager::getMonitorRuleFor(const SP<CMonitor> PMONITOR) {
auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule {
const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR);

if (!CONFIG)
return rule;

Debug::log(LOG, "CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {}", PMONITOR->szName);

if ((CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_MODE) || (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE)) {
Debug::log(LOG, " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz", rule.resolution.x, rule.resolution.y, rule.refreshRate, CONFIG->resolution.x,
CONFIG->resolution.y, CONFIG->refresh / 1000.F);
rule.resolution = CONFIG->resolution;
rule.refreshRate = CONFIG->refresh / 1000.F;
}

if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
Debug::log(LOG, " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f}", rule.offset.x, rule.offset.y, CONFIG->position.x, CONFIG->position.y);
rule.offset = CONFIG->position;
}

if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
Debug::log(LOG, " > overriding transform: {} -> {}", (uint8_t)rule.transform, (uint8_t)CONFIG->transform);
rule.transform = CONFIG->transform;
}

if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
Debug::log(LOG, " > overriding scale: {} -> {}", (uint8_t)rule.scale, (uint8_t)CONFIG->scale);
rule.scale = CONFIG->scale;
}

if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
Debug::log(LOG, " > overriding vrr: {} -> {}", rule.vrr.value_or(0), CONFIG->adaptiveSync);
rule.vrr = (int)CONFIG->adaptiveSync;
}

return rule;
};

for (auto const& r : m_dMonitorRules | std::views::reverse) {
if (PMONITOR.matchesStaticSelector(r.name)) {
return r;
if (PMONITOR->matchesStaticSelector(r.name)) {
return applyWlrOutputConfig(r);
}
}

Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName);
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR->szName);

for (auto const& r : m_dMonitorRules) {
if (r.name.empty()) {
return r;
return applyWlrOutputConfig(r);
}
}

Debug::log(WARN, "No rules configured. Using the default hardcoded one.");

return SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
.name = "",
.resolution = Vector2D(0, 0),
.offset = Vector2D(-INT32_MAX, -INT32_MAX),
.scale = -1}; // 0, 0 is preferred and -1, -1 is auto
return applyWlrOutputConfig(SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
.name = "",
.resolution = Vector2D(0, 0),
.offset = Vector2D(-INT32_MAX, -INT32_MAX),
.scale = -1}); // 0, 0 is preferred and -1, -1 is auto
}

SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) {
Expand Down Expand Up @@ -1395,7 +1434,7 @@ void CConfigManager::performMonitorReload() {
if (!m->output || m->isUnsafeFallback)
continue;

auto rule = getMonitorRuleFor(*m);
auto rule = getMonitorRuleFor(m);

if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
overAgain = true;
Expand Down Expand Up @@ -1452,7 +1491,7 @@ void CConfigManager::ensureMonitorStatus() {
if (!rm->output || rm->isUnsafeFallback)
continue;

auto rule = getMonitorRuleFor(*rm);
auto rule = getMonitorRuleFor(rm);

if (rule.disabled == rm->m_bEnabled)
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
Expand Down
2 changes: 1 addition & 1 deletion src/config/ConfigManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class CConfigManager {
static std::string getMainConfigPath();
const std::string getConfigString();

SMonitorRule getMonitorRuleFor(const CMonitor&);
SMonitorRule getMonitorRuleFor(const SP<CMonitor>);
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
std::string getDefaultWorkspaceFor(const std::string&);

Expand Down
4 changes: 2 additions & 2 deletions src/helpers/Monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void CMonitor::onConnect(bool noRule) {
createdByUser = true; // should be true. WL and Headless backends should be addable / removable

// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(self.lock());

// if it's disabled, disable and ignore
if (monitorRule.disabled) {
Expand Down Expand Up @@ -488,7 +488,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
pMirrorOf = nullptr;

// set rule
const auto RULE = g_pConfigManager->getMonitorRuleFor(*this);
const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock());

vecPosition = RULE.offset;

Expand Down
2 changes: 1 addition & 1 deletion src/managers/KeybindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) {
if (!m->output)
continue;

auto rule = g_pConfigManager->getMonitorRuleFor(*m);
auto rule = g_pConfigManager->getMonitorRuleFor(m);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
overAgain = true;
break;
Expand Down
115 changes: 77 additions & 38 deletions src/protocols/OutputManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,15 @@ COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resour

LOGM(LOG, "disableHead on {}", PMONITOR->szName);

PMONITOR->activeMonitorRule.disabled = true;
if (!g_pConfigManager->replaceMonitorRule(PMONITOR->activeMonitorRule))
g_pConfigManager->appendMonitorRule(PMONITOR->activeMonitorRule);
g_pHyprRenderer->applyMonitorRule(PMONITOR, &PMONITOR->activeMonitorRule, false);
SWlrManagerSavedOutputState newState;
if (owner->monitorStates.contains(PMONITOR->szName))
newState = owner->monitorStates.at(PMONITOR->szName);

newState.enabled = false;

g_pConfigManager->m_bWantsMonitorReload = true;

owner->monitorStates[PMONITOR->szName] = newState;
});

resource->setTest([this](CZwlrOutputConfigurationV1* r) {
Expand Down Expand Up @@ -346,6 +351,11 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {

LOGM(LOG, "Applying configuration");

if (!owner) {
LOGM(ERR, "applyTestConfiguration: no owner?!");
return false;
}

for (auto const& headw : heads) {
auto head = headw.lock();

Expand All @@ -357,41 +367,59 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
if (!PMONITOR)
continue;

LOGM(LOG, "Applying config for monitor {}", PMONITOR->szName);
LOGM(LOG, "Saving config for monitor {}", PMONITOR->szName);

SWlrManagerSavedOutputState newState;
if (owner->monitorStates.contains(PMONITOR->szName))
newState = owner->monitorStates.at(PMONITOR->szName);

SMonitorRule newRule = PMONITOR->activeMonitorRule;
newRule.name = PMONITOR->szName;
newRule.disabled = false;
newState.enabled = true;

if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
newRule.resolution = head->state.mode->getMode()->pixelSize;
newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F;
} else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
newRule.resolution = head->state.customMode.size;
newRule.refreshRate = head->state.customMode.refresh / 1000.F;
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
newState.resolution = head->state.mode->getMode()->pixelSize;
newState.refresh = head->state.mode->getMode()->refreshRate;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE;
LOGM(LOG, " > Mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh);
} else if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
newState.resolution = head->state.customMode.size;
newState.refresh = head->state.customMode.refresh;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
LOGM(LOG, " > Custom mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh);
}

if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION)
newRule.offset = head->state.position;
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) {
newState.position = head->state.position;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION;
LOGM(LOG, " > Position: {:.0f}, {:.0f}", head->state.position.x, head->state.position.y);
}

if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC)
newRule.vrr = head->state.adaptiveSync;
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
newState.adaptiveSync = head->state.adaptiveSync;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
LOGM(LOG, " > vrr: {}", newState.adaptiveSync);
}

if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE)
newRule.scale = head->state.scale;
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) {
newState.scale = head->state.scale;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE;
LOGM(LOG, " > scale: {:.2f}", newState.scale);
}

if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM)
newRule.transform = head->state.transform;
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) {
newState.transform = head->state.transform;
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM;
LOGM(LOG, " > transform: {}", (uint8_t)newState.transform);
}

// reset properties for next set.
head->committedProperties = 0;
head->state.committedProperties = 0;

if (!g_pConfigManager->replaceMonitorRule(newRule))
g_pConfigManager->appendMonitorRule(newRule);
g_pConfigManager->m_bWantsMonitorReload = true;

owner->monitorStates[PMONITOR->szName] = newState;
}

LOGM(LOG, "Applied configuration");
LOGM(LOG, "Saved configuration");

return true;
}
Expand All @@ -417,12 +445,12 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_MODE) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_MODE) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
state.mode = MODE;

LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate);
Expand All @@ -434,7 +462,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}
Expand All @@ -444,7 +472,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
state.customMode = {{w, h}, (uint32_t)refresh};

LOGM(LOG, " | configHead for {}: set custom mode to {}x{}@{}", pMonitor->szName, w, h, refresh);
Expand All @@ -456,12 +484,12 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION;
state.position = {x, y};

LOGM(LOG, " | configHead for {}: set pos to {}, {}", pMonitor->szName, x, y);
Expand All @@ -473,7 +501,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}
Expand All @@ -483,7 +511,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_TRANSFORM;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_TRANSFORM;
state.transform = (wl_output_transform)transform;

LOGM(LOG, " | configHead for {}: set transform to {}", pMonitor->szName, transform);
Expand All @@ -495,7 +523,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}
Expand All @@ -507,7 +535,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_SCALE;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_SCALE;
state.scale = scale;

LOGM(LOG, " | configHead for {}: set scale to {:.2f}", pMonitor->szName, scale);
Expand All @@ -519,7 +547,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

if (committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
return;
}
Expand All @@ -529,7 +557,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
return;
}

committedProperties |= OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
state.committedProperties |= OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
state.adaptiveSync = as;

LOGM(LOG, " | configHead for {}: set adaptiveSync to {}", pMonitor->szName, as);
Expand Down Expand Up @@ -601,3 +629,14 @@ SP<COutputMode> COutputManagementProtocol::modeFromResource(wl_resource* r) {

return nullptr;
}

SP<SWlrManagerSavedOutputState> COutputManagementProtocol::getOutputStateFor(SP<CMonitor> pMonitor) {
for (auto const& m : m_vManagers) {
if (!m->monitorStates.contains(pMonitor->szName))
continue;

return makeShared<SWlrManagerSavedOutputState>(m->monitorStates.at(pMonitor->szName));
}

return nullptr;
}
Loading

0 comments on commit 2ab4ae5

Please sign in to comment.