diff --git a/backends/xrandr/xrandr.h b/backends/xrandr/xrandr.h --- a/backends/xrandr/xrandr.h +++ b/backends/xrandr/xrandr.h @@ -57,6 +57,8 @@ static xcb_screen_t* screen(); static xcb_window_t rootWindow(); + static bool hasProperty(xcb_randr_output_t outputId, const QByteArray &name); + private Q_SLOTS: void outputChanged(xcb_randr_output_t output, xcb_randr_crtc_t crtc, diff --git a/backends/xrandr/xrandr.cpp b/backends/xrandr/xrandr.cpp --- a/backends/xrandr/xrandr.cpp +++ b/backends/xrandr/xrandr.cpp @@ -277,6 +277,18 @@ return edid; } +bool XRandR::hasProperty(xcb_randr_output_t output, const QByteArray& name) +{ + xcb_generic_error_t *error = nullptr; + auto atom = XCB::InternAtom(false, name.length(), name.constData())->atom; + auto cookie = xcb_randr_get_output_property(XCB::connection(), output, atom, XCB_ATOM_ANY, 0, 1, false, false); + auto prop_reply = xcb_randr_get_output_property_reply (XCB::connection(), cookie, &error); + + const bool ret = prop_reply->num_items == 1; + free(prop_reply); + return ret; +} + xcb_randr_get_screen_resources_reply_t* XRandR::screenResources() { if (XRandR::s_has_1_3) { diff --git a/backends/xrandr/xrandroutput.h b/backends/xrandr/xrandroutput.h --- a/backends/xrandr/xrandroutput.h +++ b/backends/xrandr/xrandroutput.h @@ -90,6 +90,7 @@ mutable QByteArray m_edid; unsigned int m_widthMm; unsigned int m_heightMm; + bool m_hotplugModeUpdate = false; XRandRCrtc *m_crtc; }; diff --git a/backends/xrandr/xrandroutput.cpp b/backends/xrandr/xrandroutput.cpp --- a/backends/xrandr/xrandroutput.cpp +++ b/backends/xrandr/xrandroutput.cpp @@ -155,6 +155,7 @@ updateModes(outputInfo); } + m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); } // A monitor has been enabled or disabled @@ -208,6 +209,7 @@ if (m_crtc) { m_crtc->connectOutput(m_id); } + m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); updateModes(outputInfo); } @@ -304,6 +306,10 @@ kscreenOutput->setName(m_name); kscreenOutput->setIcon(m_icon); + //See https://bugzilla.redhat.com/show_bug.cgi?id=1290586 + //QXL will be creating a new mode we need to jump to every time the display is resized + kscreenOutput->setFollowPreferredMode(m_hotplugModeUpdate); + kscreenOutput->setConnected(isConnected()); if (isConnected()) { KScreen::ModeList kscreenModes; diff --git a/src/configserializer.cpp b/src/configserializer.cpp --- a/src/configserializer.cpp +++ b/src/configserializer.cpp @@ -86,6 +86,7 @@ obj[QLatin1String("currentModeId")] = output->currentModeId(); obj[QLatin1String("preferredModes")] = serializeList(output->preferredModes()); obj[QLatin1String("connected")] = output->isConnected(); + obj[QLatin1String("followPreferredMode")] = output->followPreferredMode(); obj[QLatin1String("enabled")] = output->isEnabled(); obj[QLatin1String("primary")] = output->isPrimary(); obj[QLatin1String("clones")] = serializeList(output->clones()); @@ -242,6 +243,8 @@ output->setPreferredModes(deserializeList(value.value())); } else if (key == QLatin1String("connected")) { output->setConnected(value.toBool()); + } else if (key == QLatin1String("followPreferredMode")) { + output->setFollowPreferredMode(value.toBool()); } else if (key == QLatin1String("enabled")) { output->setEnabled(value.toBool()); } else if (key == QLatin1String("primary")) { diff --git a/src/output.h b/src/output.h --- a/src/output.h +++ b/src/output.h @@ -59,6 +59,7 @@ Q_PROPERTY(KScreen::Edid* edid READ edid CONSTANT) Q_PROPERTY(QSize sizeMm READ sizeMm CONSTANT) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) + Q_PROPERTY(bool followPreferredMode READ followPreferredMode WRITE setFollowPreferredMode NOTIFY followPreferredModeChanged) enum Type { @@ -211,6 +212,21 @@ */ void setScale(qreal factor); + /** + * @returns whether the mode should be changed to the new preferred mode + * once it changes + * + * @since 5.15 + */ + bool followPreferredMode() const; + + /** + * Set whether the preferred mode should be followed through @arg follow + * + * @since 5.15 + */ + void setFollowPreferredMode(bool follow); + void apply(const OutputPtr &other); Q_SIGNALS: void outputChanged(); @@ -223,6 +239,7 @@ void isPrimaryChanged(); void clonesChanged(); void scaleChanged(); + void followPreferredModeChanged(bool followPreferredMode); /** The mode list changed. * diff --git a/src/output.cpp b/src/output.cpp --- a/src/output.cpp +++ b/src/output.cpp @@ -60,7 +60,8 @@ scale(other.scale), connected(other.connected), enabled(other.enabled), - primary(other.primary) + primary(other.primary), + followPreferredMode(other.followPreferredMode) { Q_FOREACH (const ModePtr &otherMode, other.modeList) { modeList.insert(otherMode->id(), otherMode->clone()); @@ -90,6 +91,7 @@ bool connected; bool enabled; bool primary; + bool followPreferredMode = false; mutable QPointer edid; }; @@ -479,6 +481,19 @@ d->sizeMm = size; } +bool KScreen::Output::followPreferredMode() const +{ + return d->followPreferredMode; +} + +void KScreen::Output::setFollowPreferredMode(bool follow) +{ + if (follow != d->followPreferredMode) { + d->followPreferredMode = follow; + Q_EMIT followPreferredModeChanged(follow); + } +} + QRect Output::geometry() const { if (!currentMode()) { @@ -588,6 +603,7 @@ << "pos:" << output->pos() << "res:" << output->size() << "modeId:" << output->currentModeId() << "scale:" << output->scale() + << "followPreferredMode:" << output->followPreferredMode() << ")"; } else { dbg << "KScreen::Output(NULL)";