outputconfigurationstore: split user configured and automatically set modes
If the mode the user has previously set through KScreen isn't available, this falls back to a different mode without overwriting the user preference. If on the next hotplug, the desired mode is available again, it then gets chosen instead of the fallback BUG: 484037
This commit is contained in:
parent
c9627dc60f
commit
8c25784070
6 changed files with 58 additions and 11 deletions
|
@ -405,6 +405,8 @@ void DrmOutput::applyQueuedChanges(const std::shared_ptr<OutputChangeSet> &props
|
|||
next.vrrPolicy = props->vrrPolicy.value_or(m_state.vrrPolicy);
|
||||
next.colorProfileSource = props->colorProfileSource.value_or(m_state.colorProfileSource);
|
||||
next.brightness = props->brightness.value_or(m_state.brightness);
|
||||
next.desiredModeSize = props->desiredModeSize.value_or(m_state.desiredModeSize);
|
||||
next.desiredModeRefreshRate = props->desiredModeRefreshRate.value_or(m_state.desiredModeRefreshRate);
|
||||
setState(next);
|
||||
|
||||
if (!isEnabled() && m_pipeline->needsModeset()) {
|
||||
|
|
|
@ -487,6 +487,16 @@ std::shared_ptr<OutputMode> Output::currentMode() const
|
|||
return m_state.currentMode;
|
||||
}
|
||||
|
||||
QSize Output::desiredModeSize() const
|
||||
{
|
||||
return m_state.desiredModeSize;
|
||||
}
|
||||
|
||||
uint32_t Output::desiredModeRefreshRate() const
|
||||
{
|
||||
return m_state.desiredModeRefreshRate;
|
||||
}
|
||||
|
||||
Output::SubPixel Output::subPixel() const
|
||||
{
|
||||
return m_information.subPixel;
|
||||
|
@ -512,6 +522,8 @@ void Output::applyChanges(const OutputConfiguration &config)
|
|||
next.iccProfile = IccProfile::load(*props->iccProfilePath);
|
||||
}
|
||||
next.vrrPolicy = props->vrrPolicy.value_or(m_state.vrrPolicy);
|
||||
next.desiredModeSize = props->desiredModeSize.value_or(m_state.desiredModeSize);
|
||||
next.desiredModeRefreshRate = props->desiredModeRefreshRate.value_or(m_state.desiredModeRefreshRate);
|
||||
|
||||
setState(next);
|
||||
|
||||
|
|
|
@ -321,6 +321,8 @@ public:
|
|||
const Edid &edid() const;
|
||||
QList<std::shared_ptr<OutputMode>> modes() const;
|
||||
std::shared_ptr<OutputMode> currentMode() const;
|
||||
QSize desiredModeSize() const;
|
||||
uint32_t desiredModeRefreshRate() const;
|
||||
DpmsMode dpmsMode() const;
|
||||
virtual void setDpmsMode(DpmsMode mode);
|
||||
|
||||
|
@ -457,6 +459,8 @@ protected:
|
|||
OutputTransform manualTransform = OutputTransform::Normal;
|
||||
QList<std::shared_ptr<OutputMode>> modes;
|
||||
std::shared_ptr<OutputMode> currentMode;
|
||||
QSize desiredModeSize;
|
||||
uint32_t desiredModeRefreshRate = 0;
|
||||
DpmsMode dpmsMode = DpmsMode::On;
|
||||
SubPixel subPixel = SubPixel::Unknown;
|
||||
bool enabled = false;
|
||||
|
|
|
@ -24,6 +24,8 @@ class KWIN_EXPORT OutputChangeSet
|
|||
{
|
||||
public:
|
||||
std::optional<std::weak_ptr<OutputMode>> mode;
|
||||
std::optional<QSize> desiredModeSize;
|
||||
std::optional<uint32_t> desiredModeRefreshRate;
|
||||
std::optional<bool> enabled;
|
||||
std::optional<QPoint> pos;
|
||||
std::optional<double> scale;
|
||||
|
|
|
@ -200,9 +200,13 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
|
|||
outputIt = setup->outputs.end() - 1;
|
||||
}
|
||||
if (const auto changeSet = config.constChangeSet(output)) {
|
||||
std::shared_ptr<OutputMode> mode = changeSet->mode.value_or(output->currentMode()).lock();
|
||||
if (!mode) {
|
||||
mode = output->currentMode();
|
||||
QSize modeSize = changeSet->desiredModeSize.value_or(output->desiredModeSize());
|
||||
if (modeSize.isEmpty()) {
|
||||
modeSize = output->currentMode()->size();
|
||||
}
|
||||
uint32_t refreshRate = changeSet->desiredModeRefreshRate.value_or(output->desiredModeRefreshRate());
|
||||
if (refreshRate == 0) {
|
||||
refreshRate = output->currentMode()->refreshRate();
|
||||
}
|
||||
m_outputs[*outputIndex] = OutputState{
|
||||
.edidIdentifier = output->edid().identifier(),
|
||||
|
@ -210,8 +214,8 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
|
|||
.edidHash = output->edid().isValid() ? output->edid().hash() : QString{},
|
||||
.mstPath = output->mstPath(),
|
||||
.mode = ModeData{
|
||||
.size = mode->size(),
|
||||
.refreshRate = mode->refreshRate(),
|
||||
.size = modeSize,
|
||||
.refreshRate = refreshRate,
|
||||
},
|
||||
.scale = changeSet->scale.value_or(output->scale()),
|
||||
.transform = changeSet->transform.value_or(output->transform()),
|
||||
|
@ -238,15 +242,22 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
|
|||
.priority = int(outputOrder.indexOf(output)),
|
||||
};
|
||||
} else {
|
||||
const auto mode = output->currentMode();
|
||||
QSize modeSize = output->desiredModeSize();
|
||||
if (modeSize.isEmpty()) {
|
||||
modeSize = output->currentMode()->size();
|
||||
}
|
||||
uint32_t refreshRate = output->desiredModeRefreshRate();
|
||||
if (refreshRate == 0) {
|
||||
refreshRate = output->currentMode()->refreshRate();
|
||||
}
|
||||
m_outputs[*outputIndex] = OutputState{
|
||||
.edidIdentifier = output->edid().identifier(),
|
||||
.connectorName = output->name(),
|
||||
.edidHash = output->edid().isValid() ? output->edid().hash() : QString{},
|
||||
.mstPath = output->mstPath(),
|
||||
.mode = ModeData{
|
||||
.size = mode->size(),
|
||||
.refreshRate = mode->refreshRate(),
|
||||
.size = modeSize,
|
||||
.refreshRate = refreshRate,
|
||||
},
|
||||
.scale = output->scale(),
|
||||
.transform = output->transform(),
|
||||
|
@ -287,13 +298,19 @@ std::pair<OutputConfiguration, QList<Output *>> OutputConfigurationStore::setupT
|
|||
return state.outputIndex == outputIndex;
|
||||
});
|
||||
const auto modes = output->modes();
|
||||
const auto mode = std::find_if(modes.begin(), modes.end(), [&state](const auto &mode) {
|
||||
const auto modeIt = std::find_if(modes.begin(), modes.end(), [&state](const auto &mode) {
|
||||
return state.mode
|
||||
&& mode->size() == state.mode->size
|
||||
&& mode->refreshRate() == state.mode->refreshRate;
|
||||
});
|
||||
std::optional<std::shared_ptr<OutputMode>> mode = modeIt == modes.end() ? std::nullopt : std::optional(*modeIt);
|
||||
if (!mode.has_value()) {
|
||||
mode = chooseMode(output);
|
||||
}
|
||||
*ret.changeSet(output) = OutputChangeSet{
|
||||
.mode = mode == modes.end() ? std::nullopt : std::optional(*mode),
|
||||
.mode = mode,
|
||||
.desiredModeSize = state.mode.has_value() ? std::make_optional(state.mode->size) : std::nullopt,
|
||||
.desiredModeRefreshRate = state.mode.has_value() ? std::make_optional(state.mode->refreshRate) : std::nullopt,
|
||||
.enabled = setupState.enabled,
|
||||
.pos = setupState.position,
|
||||
.scale = state.scale,
|
||||
|
@ -420,6 +437,8 @@ std::pair<OutputConfiguration, QList<Output *>> OutputConfigurationStore::genera
|
|||
const auto changeset = ret.changeSet(output);
|
||||
*changeset = {
|
||||
.mode = mode,
|
||||
.desiredModeSize = mode->size(),
|
||||
.desiredModeRefreshRate = mode->refreshRate(),
|
||||
.enabled = kscreenChangeSet.enabled.value_or(enable),
|
||||
.pos = pos,
|
||||
// kscreen scale is unreliable because it gets overwritten with the value 1 on Xorg,
|
||||
|
|
|
@ -121,7 +121,15 @@ void OutputConfigurationV2Interface::kde_output_configuration_v2_mode(Resource *
|
|||
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
|
||||
OutputDeviceModeV2Interface *mode = OutputDeviceModeV2Interface::get(modeResource);
|
||||
if (output && mode) {
|
||||
config.changeSet(output->handle())->mode = mode->handle().lock();
|
||||
const auto change = config.changeSet(output->handle());
|
||||
const auto modePtr = mode->handle().lock();
|
||||
if (!modePtr) {
|
||||
invalid = true;
|
||||
return;
|
||||
}
|
||||
change->mode = modePtr;
|
||||
change->desiredModeSize = modePtr->size();
|
||||
change->desiredModeRefreshRate = modePtr->refreshRate();
|
||||
} else {
|
||||
invalid = true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue