diff --git a/backends/xrandr/xrandr.cpp b/backends/xrandr/xrandr.cpp index 3de5d51..e740c0e 100644 --- a/backends/xrandr/xrandr.cpp +++ b/backends/xrandr/xrandr.cpp @@ -1,320 +1,330 @@ /************************************************************************************* * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2012, 2013 by Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - #include "xrandr.h" + #include "xrandrconfig.h" #include "xrandrscreen.h" #include "../xcbwrapper.h" #include "../xcbeventlistener.h" #include "config.h" -#include "output.h" #include "edid.h" +#include "output.h" -#include #include -#include #include #include #include -#include xcb_screen_t* XRandR::s_screen = nullptr; xcb_window_t XRandR::s_rootWindow = 0; XRandRConfig* XRandR::s_internalConfig = nullptr; int XRandR::s_randrBase = 0; int XRandR::s_randrError = 0; bool XRandR::s_monitorInitialized = false; bool XRandR::s_has_1_3 = false; bool XRandR::s_xorgCacheInitialized = false; using namespace KScreen; Q_LOGGING_CATEGORY(KSCREEN_XRANDR, "kscreen.xrandr") XRandR::XRandR() : KScreen::AbstractBackend() , m_x11Helper(nullptr) , m_isValid(false) , m_configChangeCompressor(nullptr) { qRegisterMetaType("xcb_randr_output_t"); qRegisterMetaType("xcb_randr_crtc_t"); qRegisterMetaType("xcb_randr_mode_t"); qRegisterMetaType("xcb_randr_connection_t"); qRegisterMetaType("xcb_randr_rotation_t"); // Use our own connection to make sure that we won't mess up Qt's connection // if something goes wrong on our side. xcb_generic_error_t *error = nullptr; xcb_randr_query_version_reply_t* version; XCB::connection(); - version = xcb_randr_query_version_reply(XCB::connection(), xcb_randr_query_version(XCB::connection(), XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION), &error); - + version = xcb_randr_query_version_reply(XCB::connection(), + xcb_randr_query_version(XCB::connection(), + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION), + &error); if (!version || error) { XCB::closeConnection(); free(error); return; } - if ((version->major_version > 1) || ((version->major_version == 1) && (version->minor_version >= 2))) { + if ((version->major_version > 1) || + ((version->major_version == 1) && (version->minor_version >= 2))) { m_isValid = true; } else { XCB::closeConnection(); qCWarning(KSCREEN_XRANDR) << "XRandR extension not available or unsupported version"; return; } if (s_screen == nullptr) { s_screen = XCB::screenOfDisplay(XCB::connection(), QX11Info::appScreen()); s_rootWindow = s_screen->root; xcb_prefetch_extension_data(XCB::connection(), &xcb_randr_id); auto reply = xcb_get_extension_data(XCB::connection(), &xcb_randr_id); s_randrBase = reply->first_event; s_randrError = reply->first_error; } - XRandR::s_has_1_3 = (version->major_version > 1 || (version->major_version == 1 && version->minor_version >= 3)); + XRandR::s_has_1_3 = (version->major_version > 1 || + (version->major_version == 1 && version->minor_version >= 3)); if (s_internalConfig == nullptr) { s_internalConfig = new XRandRConfig(); } if (!s_monitorInitialized) { m_x11Helper = new XCBEventListener(); connect(m_x11Helper, &XCBEventListener::outputChanged, this, &XRandR::outputChanged, Qt::QueuedConnection); connect(m_x11Helper, &XCBEventListener::crtcChanged, this, &XRandR::crtcChanged, Qt::QueuedConnection); connect(m_x11Helper, &XCBEventListener::screenChanged, this, &XRandR::screenChanged, Qt::QueuedConnection); m_configChangeCompressor = new QTimer(this); m_configChangeCompressor->setSingleShot(true); m_configChangeCompressor->setInterval(500); connect(m_configChangeCompressor, &QTimer::timeout, [&]() { qCDebug(KSCREEN_XRANDR) << "Emitting configChanged()"; Q_EMIT configChanged(config()); }); s_monitorInitialized = true; } } XRandR::~XRandR() { delete m_x11Helper; } QString XRandR::name() const { return QStringLiteral("XRandR"); } QString XRandR::serviceName() const { return QStringLiteral("org.kde.KScreen.Backend.XRandR"); } void XRandR::outputChanged(xcb_randr_output_t output, xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t connection) { m_configChangeCompressor->start(); XRandROutput *xOutput = s_internalConfig->output(output); if (!xOutput) { s_internalConfig->addNewOutput(output); return; } // check if this output disappeared if (crtc == XCB_NONE && mode == XCB_NONE && connection == XCB_RANDR_CONNECTION_DISCONNECTED) { XCB::OutputInfo info(output, XCB_TIME_CURRENT_TIME); if (info.isNull()) { s_internalConfig->removeOutput(output); qCDebug(KSCREEN_XRANDR) << "Output" << output << " removed"; return; } // info is valid: the output is still there } XCB::PrimaryOutput primary(XRandR::rootWindow()); xOutput->update(crtc, mode, connection, (primary->output == output)); - qCDebug(KSCREEN_XRANDR) << "Output" << xOutput->id() << ": connected =" << xOutput->isConnected() << ", enabled =" << xOutput->isEnabled(); + qCDebug(KSCREEN_XRANDR) << "Output" << xOutput->id() << ": connected =" + << xOutput->isConnected() << ", enabled =" << xOutput->isEnabled(); } void XRandR::crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect& geom) { XRandRCrtc *xCrtc = s_internalConfig->crtc(crtc); if (!xCrtc) { s_internalConfig->addNewCrtc(crtc); } else { xCrtc->update(mode, rotation, geom); } m_configChangeCompressor->start(); } void XRandR::screenChanged(xcb_randr_rotation_t rotation, const QSize &sizePx, const QSize &sizeMm) { Q_UNUSED(sizeMm); QSize newSizePx = sizePx; if (rotation == XCB_RANDR_ROTATION_ROTATE_90 || rotation == XCB_RANDR_ROTATION_ROTATE_270) { newSizePx.transpose(); } XRandRScreen *xScreen = s_internalConfig->screen(); Q_ASSERT(xScreen); xScreen->update(newSizePx); m_configChangeCompressor->start(); } ConfigPtr XRandR::config() const { return s_internalConfig->toKScreenConfig(); } void XRandR::setConfig(const ConfigPtr &config) { if (!config) { return; } qCDebug(KSCREEN_XRANDR) << "XRandR::setConfig"; s_internalConfig->applyKScreenConfig(config); qCDebug(KSCREEN_XRANDR) << "XRandR::setConfig done!"; } QByteArray XRandR::edid(int outputId) const { const XRandROutput *output = s_internalConfig->output(outputId); if (!output) { return QByteArray(); } return output->edid(); } bool XRandR::isValid() const { return m_isValid; } quint8* XRandR::getXProperty(xcb_randr_output_t output, xcb_atom_t atom, size_t &len) { quint8 *result; auto cookie = xcb_randr_get_output_property(XCB::connection(), output, atom, XCB_ATOM_ANY, 0, 100, false, false); auto reply = xcb_randr_get_output_property_reply(XCB::connection(), cookie, nullptr); + if (reply->type == XCB_ATOM_INTEGER && reply->format == 8) { result = new quint8[reply->num_items]; memcpy(result, xcb_randr_get_output_property_data(reply), reply->num_items); len = reply->num_items; } else { result = nullptr; } free(reply); return result; } QByteArray XRandR::outputEdid(xcb_randr_output_t outputId) { size_t len = 0; quint8 *result; auto edid_atom = XCB::InternAtom(false, 4, "EDID")->atom; result = XRandR::getXProperty(outputId, edid_atom, len); if (result == nullptr) { auto edid_atom = XCB::InternAtom(false, 9, "EDID_DATA")->atom; result = XRandR::getXProperty(outputId, edid_atom, len); } if (result == nullptr) { auto edid_atom = XCB::InternAtom(false, 25, "XFree86_DDC_EDID1_RAWDATA")->atom; result = XRandR::getXProperty(outputId, edid_atom, len); } QByteArray edid; if (result != nullptr) { if (len % 128 == 0) { edid = QByteArray(reinterpret_cast(result), len); } delete[] result; } 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 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) { if (XRandR::s_xorgCacheInitialized) { // HACK: This abuses the fact that xcb_randr_get_screen_resources_reply_t // and xcb_randr_get_screen_resources_current_reply_t are the same return reinterpret_cast( xcb_randr_get_screen_resources_current_reply(XCB::connection(), - xcb_randr_get_screen_resources_current(XCB::connection(), XRandR::rootWindow()), - nullptr)); + xcb_randr_get_screen_resources_current( + XCB::connection(), + XRandR::rootWindow()), nullptr)); } else { /* XRRGetScreenResourcesCurrent is faster then XRRGetScreenResources * because it returns cached values. However the cached values are not * available until someone calls XRRGetScreenResources first. In case * we happen to be the first ones, we need to fill the cache first. */ XRandR::s_xorgCacheInitialized = true; } } return xcb_randr_get_screen_resources_reply(XCB::connection(), - xcb_randr_get_screen_resources(XCB::connection(), XRandR::rootWindow()), nullptr); + xcb_randr_get_screen_resources( + XCB::connection(), + XRandR::rootWindow()), + nullptr); } xcb_window_t XRandR::rootWindow() { return s_rootWindow; } xcb_screen_t* XRandR::screen() { return s_screen; } diff --git a/backends/xrandr/xrandr.h b/backends/xrandr/xrandr.h index 8d19e80..f10e25c 100644 --- a/backends/xrandr/xrandr.h +++ b/backends/xrandr/xrandr.h @@ -1,95 +1,84 @@ /************************************************************************************* * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2012, 2013 by Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - -#ifndef XRANDR_BACKEND_H -#define XRANDR_BACKEND_H +#pragma once #include "abstractbackend.h" -#include #include +#include #include "../xcbwrapper.h" class QRect; class QTimer; class XCBEventListener; class XRandRConfig; -namespace KScreen { -} class XRandR : public KScreen::AbstractBackend { Q_OBJECT Q_PLUGIN_METADATA(IID "org.kf5.kscreen.backends.xrandr") public: explicit XRandR(); ~XRandR() override; QString name() const override; QString serviceName() const override; KScreen::ConfigPtr config() const override; void setConfig(const KScreen::ConfigPtr &config) override; bool isValid() const override; QByteArray edid(int outputId) const override; static QByteArray outputEdid(xcb_randr_output_t outputId); static xcb_randr_get_screen_resources_reply_t* screenResources(); 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, - xcb_randr_mode_t mode, + private: + void outputChanged(xcb_randr_output_t output, xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t connection); - void crtcChanged(xcb_randr_crtc_t crtc, - xcb_randr_mode_t mode, - xcb_randr_rotation_t rotation, - const QRect &geom); - void screenChanged(xcb_randr_rotation_t rotation, - const QSize &sizePx, - const QSize &sizeMm); + void crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, + xcb_randr_rotation_t rotation, const QRect &geom); + void screenChanged(xcb_randr_rotation_t rotation, const QSize &sizePx, const QSize &sizeMm); - private: static quint8* getXProperty(xcb_randr_output_t output, xcb_atom_t atom, size_t &len); static xcb_screen_t *s_screen; static xcb_window_t s_rootWindow; static XRandRConfig *s_internalConfig; + static int s_randrBase; static int s_randrError; static bool s_monitorInitialized; static bool s_has_1_3; static bool s_xorgCacheInitialized; XCBEventListener *m_x11Helper; bool m_isValid; QTimer *m_configChangeCompressor; }; Q_DECLARE_LOGGING_CATEGORY(KSCREEN_XRANDR) -#endif //XRandR_BACKEND_H diff --git a/backends/xrandr/xrandrconfig.cpp b/backends/xrandr/xrandrconfig.cpp index ccc8ac8..8e31596 100644 --- a/backends/xrandr/xrandrconfig.cpp +++ b/backends/xrandr/xrandrconfig.cpp @@ -1,586 +1,635 @@ /************************************************************************************* * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2012 - 2015 by Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - #include "xrandrconfig.h" #include "xrandrscreen.h" #include "xrandr.h" #include "xrandrmode.h" #include "xrandroutput.h" #include "xrandrcrtc.h" #include "config.h" #include "output.h" #include "edid.h" #include "../xcbwrapper.h" #include #include #include using namespace KScreen; XRandRConfig::XRandRConfig() : QObject() , m_screen(nullptr) { m_screen = new XRandRScreen(this); XCB::ScopedPointer resources(XRandR::screenResources()); + xcb_randr_crtc_t *crtcs = xcb_randr_get_screen_resources_crtcs(resources.data()); - for (int i = 0, c = xcb_randr_get_screen_resources_crtcs_length(resources.data()); i < c; ++i) { + const int crtcsCount = xcb_randr_get_screen_resources_crtcs_length(resources.data()); + for (int i = 0; i < crtcsCount; ++i) { addNewCrtc(crtcs[i]); } xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data()); - for (int i = 0, c = xcb_randr_get_screen_resources_outputs_length(resources.data()); i < c; ++i) { + const int outputsCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); + for (int i = 0; i < outputsCount; ++i) { addNewOutput(outputs[i]); } } XRandRConfig::~XRandRConfig() { qDeleteAll(m_outputs); qDeleteAll(m_crtcs); delete m_screen; } XRandROutput::Map XRandRConfig::outputs() const { return m_outputs; } XRandROutput* XRandRConfig::output(xcb_randr_output_t output) const { return m_outputs[output]; } XRandRCrtc::Map XRandRConfig::crtcs() const { return m_crtcs; } XRandRCrtc* XRandRConfig::crtc(xcb_randr_crtc_t crtc) const { return m_crtcs[crtc]; } XRandRScreen* XRandRConfig::screen() const { return m_screen; } void XRandRConfig::addNewOutput(xcb_randr_output_t id) { XRandROutput *xOutput = new XRandROutput(id, this); m_outputs.insert(id, xOutput); } void XRandRConfig::addNewCrtc(xcb_randr_crtc_t crtc) { m_crtcs.insert(crtc, new XRandRCrtc(crtc, this)); } void XRandRConfig::removeOutput(xcb_randr_output_t id) { delete m_outputs.take(id); } KScreen::ConfigPtr XRandRConfig::toKScreenConfig() const { KScreen::ConfigPtr config(new KScreen::Config); + auto features = Config::Feature::Writable | Config::Feature::PrimaryDisplay; config->setSupportedFeatures(features); + KScreen::OutputList kscreenOutputs; for (auto iter = m_outputs.constBegin(); iter != m_outputs.constEnd(); ++iter) { KScreen::OutputPtr kscreenOutput = (*iter)->toKScreenOutput(); kscreenOutputs.insert(kscreenOutput->id(), kscreenOutput); } + config->setOutputs(kscreenOutputs); config->setScreen(m_screen->toKScreenScreen()); return config; } void XRandRConfig::applyKScreenConfig(const KScreen::ConfigPtr &config) { const KScreen::OutputList kscreenOutputs = config->outputs(); + const QSize newScreenSize = screenSize(config); const QSize currentScreenSize = m_screen->currentSize(); + // When the current screen configuration is bigger than the new size (like // when rotating an output), the XSetScreenSize can fail or apply the smaller // size only partially, because we apply the size (we have to) before the // output changes. To prevent all kinds of weird screen sizes from happening, // we initially set such screen size, that it can take the current as well // as the new configuration, then we apply the output changes, and finally then // (if necessary) we reduce the screen size to fix the new configuration precisely. - const QSize intermediateScreenSize = QSize(qMax(newScreenSize.width(), currentScreenSize.width()), - qMax(newScreenSize.height(), currentScreenSize.height())); + const QSize intermediateScreenSize = QSize(qMax(newScreenSize.width(), + currentScreenSize.width()), + qMax(newScreenSize.height(), + currentScreenSize.height())); + int neededCrtcs = 0; xcb_randr_output_t primaryOutput = 0; xcb_randr_output_t oldPrimaryOutput = 0; - Q_FOREACH (const XRandROutput *xrandrOutput, m_outputs) { + for (const XRandROutput *xrandrOutput : m_outputs) { if (xrandrOutput->isPrimary()) { oldPrimaryOutput = xrandrOutput->id(); break; } } KScreen::OutputList toDisable, toEnable, toChange; - Q_FOREACH(const KScreen::OutputPtr &kscreenOutput, kscreenOutputs) { + + for (const KScreen::OutputPtr &kscreenOutput : kscreenOutputs) { xcb_randr_output_t outputId = kscreenOutput->id(); XRandROutput *currentOutput = output(outputId); //Only set the output as primary if it is enabled. if (kscreenOutput->isPrimary() && kscreenOutput->isEnabled()) { primaryOutput = outputId; } const bool currentEnabled = currentOutput->isEnabled(); + if (!kscreenOutput->isEnabled() && currentEnabled) { toDisable.insert(outputId, kscreenOutput); continue; } else if (kscreenOutput->isEnabled() && !currentEnabled) { toEnable.insert(outputId, kscreenOutput); ++neededCrtcs; continue; } else if (!kscreenOutput->isEnabled() && !currentEnabled) { continue; } ++neededCrtcs; if (kscreenOutput->currentModeId() != currentOutput->currentModeId()) { if (!toChange.contains(outputId)) { toChange.insert(outputId, kscreenOutput); } } if (kscreenOutput->pos() != currentOutput->position()) { if (!toChange.contains(outputId)) { toChange.insert(outputId, kscreenOutput); } } if (kscreenOutput->rotation() != currentOutput->rotation()) { if (!toChange.contains(outputId)) { toChange.insert(outputId, kscreenOutput); } } - XRandRMode *currentMode = currentOutput->modes().value(kscreenOutput->currentModeId().toInt()); - + XRandRMode *currentMode = currentOutput->modes().value( + kscreenOutput->currentModeId().toInt()); // For some reason, in some environments currentMode is null // which doesn't make sense because it is the *current* mode... // Since we haven't been able to figure out the reason why // this happens, we are adding this debug code to try to // figure out how this happened. if (!currentMode) { qWarning() << "Current mode is null:" << "ModeId:" << currentOutput->currentModeId() << "Mode: " << currentOutput->currentMode() << "Output: " << currentOutput->id(); -// qDebug() << kRealBacktrace(256); printConfig(config); printInternalCond(); continue; } - // If the output would not fit into new screen size, we need to disable - // it and reposition it + // When the output would not fit into new screen size, we need to disable and reposition it. const QRect geom = kscreenOutput->geometry(); if (geom.right() > newScreenSize.width() || geom.bottom() > newScreenSize.height()) { if (!toDisable.contains(outputId)) { - qCDebug(KSCREEN_XRANDR) << "The new output would not fit into screen - new geometry: " << geom << ", new screen size:" << newScreenSize; + qCDebug(KSCREEN_XRANDR) + << "The new output would not fit into screen - new geometry: " << geom + << ", new screen size:" << newScreenSize; toDisable.insert(outputId, kscreenOutput); } } - } // Q_FOREACH (const KScreen::OutputPtr &kscreenOutput, kscreenOutputs) + } const KScreen::ScreenPtr kscreenScreen = config->screen(); if (newScreenSize.width() > kscreenScreen->maxSize().width() || newScreenSize.height() > kscreenScreen->maxSize().height()) { - qCDebug(KSCREEN_XRANDR) << "The new screen size is too big - requested: " << newScreenSize << ", maximum: " << kscreenScreen->maxSize(); + qCDebug(KSCREEN_XRANDR) << "The new screen size is too big - requested: " + << newScreenSize << ", maximum: " << kscreenScreen->maxSize(); return; } qCDebug(KSCREEN_XRANDR) << "Needed CRTCs: " << neededCrtcs; - XCB::ScopedPointer screenResources(XRandR::screenResources()); + + XCB::ScopedPointer + screenResources(XRandR::screenResources()); + if (neededCrtcs > screenResources->num_crtcs) { - qCDebug(KSCREEN_XRANDR) << "We need more CRTCs than we have available - requested: " << neededCrtcs << ", available: " << screenResources->num_crtcs; + qCDebug(KSCREEN_XRANDR) << "We need more CRTCs than we have available - requested: " + << neededCrtcs << ", available: " << screenResources->num_crtcs; return; } - qCDebug(KSCREEN_XRANDR) << "Actions to perform:"; - qCDebug(KSCREEN_XRANDR) << "\tPrimary Output:" << (primaryOutput != oldPrimaryOutput); + qCDebug(KSCREEN_XRANDR) << "Actions to perform:" << "\n" + << "\tPrimary Output:" << (primaryOutput != oldPrimaryOutput); if (primaryOutput != oldPrimaryOutput) { - qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << oldPrimaryOutput; - qCDebug(KSCREEN_XRANDR) << "\t\tNew:" << primaryOutput; + qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << oldPrimaryOutput << "\n" + << "\t\tNew:" << primaryOutput; } + qCDebug(KSCREEN_XRANDR) << "\tChange Screen Size:" << (newScreenSize != currentScreenSize); if (newScreenSize != currentScreenSize) { - qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << currentScreenSize; - qCDebug(KSCREEN_XRANDR) << "\t\tIntermediate:" << intermediateScreenSize; - qCDebug(KSCREEN_XRANDR) << "\t\tNew:" << newScreenSize; + qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << currentScreenSize << "\n" + << "\t\tIntermediate:" << intermediateScreenSize << "\n" + << "\t\tNew:" << newScreenSize; } + qCDebug(KSCREEN_XRANDR) << "\tDisable outputs:" << !toDisable.isEmpty(); if (!toDisable.isEmpty()) { qCDebug(KSCREEN_XRANDR) << "\t\t" << toDisable.keys(); } + qCDebug(KSCREEN_XRANDR) << "\tChange outputs:" << !toChange.isEmpty(); if (!toChange.isEmpty()) { qCDebug(KSCREEN_XRANDR) << "\t\t" << toChange.keys(); } + qCDebug(KSCREEN_XRANDR) << "\tEnable outputs:" << !toEnable.isEmpty(); if (!toEnable.isEmpty()) { qCDebug(KSCREEN_XRANDR) << "\t\t" << toEnable.keys(); } // Grab the server so that no-one else can do changes to XRandR and to block // change notifications until we are done XCB::GrabServer grabber; //If there is nothing to do, not even bother - if (oldPrimaryOutput == primaryOutput && toDisable.isEmpty() && toEnable.isEmpty() && toChange.isEmpty()) { + if (oldPrimaryOutput == primaryOutput && toDisable.isEmpty() && + toEnable.isEmpty() && toChange.isEmpty()) { if (newScreenSize != currentScreenSize) { setScreenSize(newScreenSize); } return; } - Q_FOREACH(const KScreen::OutputPtr &output, toDisable) { + for (const KScreen::OutputPtr &output : toDisable) { disableOutput(output); } if (intermediateScreenSize != currentScreenSize) { setScreenSize(intermediateScreenSize); } bool forceScreenSizeUpdate = false; - Q_FOREACH(const KScreen::OutputPtr &output, toChange) { + + for (const KScreen::OutputPtr &output : toChange) { if (!changeOutput(output)) { /* If we disabled the output before changing it and XRandR failed * to re-enable it, then update screen size too */ if (toDisable.contains(output->id())) { //output->setEnabled(false); qCDebug(KSCREEN_XRANDR) << "Output failed to change: " << output->name(); forceScreenSizeUpdate = true; } } } - Q_FOREACH(const KScreen::OutputPtr &output, toEnable) { + for (const KScreen::OutputPtr &output : toEnable) { if (!enableOutput(output)) { //output->setEnabled(false); qCDebug(KSCREEN_XRANDR) << "Output failed to be Enabled: " << output->name(); forceScreenSizeUpdate = true; } } if (oldPrimaryOutput != primaryOutput) { setPrimaryOutput(primaryOutput); } if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) { QSize newSize = newScreenSize; if (forceScreenSizeUpdate) { newSize = screenSize(config); qCDebug(KSCREEN_XRANDR) << "Forced to change screen size: " << newSize; } setScreenSize(newSize); } } void XRandRConfig::printConfig(const ConfigPtr &config) const { qCDebug(KSCREEN_XRANDR) << "KScreen version:" /*<< LIBKSCREEN_VERSION*/; if (!config) { qCDebug(KSCREEN_XRANDR) << "Config is invalid"; return; } if (!config->screen()) { qCDebug(KSCREEN_XRANDR) << "No screen in the configuration, broken backend"; return; } - qCDebug(KSCREEN_XRANDR) << "Screen:"; - qCDebug(KSCREEN_XRANDR) << "\tmaxSize:" << config->screen()->maxSize(); - qCDebug(KSCREEN_XRANDR) << "\tminSize:" << config->screen()->minSize(); - qCDebug(KSCREEN_XRANDR) << "\tcurrentSize:" << config->screen()->currentSize(); + qCDebug(KSCREEN_XRANDR) << "Screen:" << "\n" + << "\tmaxSize:" << config->screen()->maxSize() << "\n" + << "\tminSize:" << config->screen()->minSize() << "\n" + << "\tcurrentSize:" << config->screen()->currentSize(); + + const OutputList outputs = config->outputs(); + for (const OutputPtr &output : outputs) { + qCDebug(KSCREEN_XRANDR) << "\n-----------------------------------------------------\n" << "\n" + << "Id: " << output->id() << "\n" + << "Name: " << output->name() << "\n" + << "Type: " << output->type() << "\n" + << "Connected: " << output->isConnected(); - OutputList outputs = config->outputs(); - Q_FOREACH(const OutputPtr &output, outputs) { - qCDebug(KSCREEN_XRANDR) << "\n-----------------------------------------------------\n"; - qCDebug(KSCREEN_XRANDR) << "Id: " << output->id(); - qCDebug(KSCREEN_XRANDR) << "Name: " << output->name(); - qCDebug(KSCREEN_XRANDR) << "Type: " << output->type(); - qCDebug(KSCREEN_XRANDR) << "Connected: " << output->isConnected(); if (!output->isConnected()) { continue; } - qCDebug(KSCREEN_XRANDR) << "Enabled: " << output->isEnabled(); - qCDebug(KSCREEN_XRANDR) << "Primary: " << output->isPrimary(); - qCDebug(KSCREEN_XRANDR) << "Rotation: " << output->rotation(); - qCDebug(KSCREEN_XRANDR) << "Pos: " << output->pos(); - qCDebug(KSCREEN_XRANDR) << "MMSize: " << output->sizeMm(); + + qCDebug(KSCREEN_XRANDR) << "Enabled: " << output->isEnabled() << "\n" + << "Primary: " << output->isPrimary() << "\n" + << "Rotation: " << output->rotation() << "\n" + << "Pos: " << output->pos() << "\n" + << "MMSize: " << output->sizeMm(); if (output->currentMode()) { qCDebug(KSCREEN_XRANDR) << "Size: " << output->currentMode()->size(); } - if (output->clones().isEmpty()) { - qCDebug(KSCREEN_XRANDR) << "Clones: " << "None"; - } else { - qCDebug(KSCREEN_XRANDR) << "Clones: " << output->clones().count(); - } - qCDebug(KSCREEN_XRANDR) << "Mode: " << output->currentModeId(); - qCDebug(KSCREEN_XRANDR) << "Preferred Mode: " << output->preferredModeId(); - qCDebug(KSCREEN_XRANDR) << "Preferred modes: " << output->preferredModes(); - qCDebug(KSCREEN_XRANDR) << "Modes: "; + + qCDebug(KSCREEN_XRANDR) << "Clones: " + << (output->clones().isEmpty() ? QStringLiteral("None") : + QString::number(output->clones().count())) + << "\n" + << "Mode: " << output->currentModeId() << "\n" + << "Preferred Mode: " << output->preferredModeId() << "\n" + << "Preferred modes: " << output->preferredModes() << "\n" + << "Modes: "; ModeList modes = output->modes(); - Q_FOREACH(const ModePtr &mode, modes) { - qCDebug(KSCREEN_XRANDR) << "\t" << mode->id() << " " << mode->name() << " " << mode->size() << " " << mode->refreshRate(); + for (const ModePtr &mode : modes) { + qCDebug(KSCREEN_XRANDR) << "\t" << mode->id() << " " << mode->name() << " " + << mode->size() << " " << mode->refreshRate(); } Edid* edid = output->edid(); qCDebug(KSCREEN_XRANDR) << "EDID Info: "; if (edid && edid->isValid()) { - qCDebug(KSCREEN_XRANDR) << "\tDevice ID: " << edid->deviceId(); - qCDebug(KSCREEN_XRANDR) << "\tName: " << edid->name(); - qCDebug(KSCREEN_XRANDR) << "\tVendor: " << edid->vendor(); - qCDebug(KSCREEN_XRANDR) << "\tSerial: " << edid->serial(); - qCDebug(KSCREEN_XRANDR) << "\tEISA ID: " << edid->eisaId(); - qCDebug(KSCREEN_XRANDR) << "\tHash: " << edid->hash(); - qCDebug(KSCREEN_XRANDR) << "\tWidth: " << edid->width(); - qCDebug(KSCREEN_XRANDR) << "\tHeight: " << edid->height(); - qCDebug(KSCREEN_XRANDR) << "\tGamma: " << edid->gamma(); - qCDebug(KSCREEN_XRANDR) << "\tRed: " << edid->red(); - qCDebug(KSCREEN_XRANDR) << "\tGreen: " << edid->green(); - qCDebug(KSCREEN_XRANDR) << "\tBlue: " << edid->blue(); - qCDebug(KSCREEN_XRANDR) << "\tWhite: " << edid->white(); + qCDebug(KSCREEN_XRANDR) << "\tDevice ID: " << edid->deviceId() << "\n" + << "\tName: " << edid->name() << "\n" + << "\tVendor: " << edid->vendor() << "\n" + << "\tSerial: " << edid->serial() << "\n" + << "\tEISA ID: " << edid->eisaId() << "\n" + << "\tHash: " << edid->hash() << "\n" + << "\tWidth: " << edid->width() << "\n" + << "\tHeight: " << edid->height() << "\n" + << "\tGamma: " << edid->gamma() << "\n" + << "\tRed: " << edid->red() << "\n" + << "\tGreen: " << edid->green() << "\n" + << "\tBlue: " << edid->blue() << "\n" + << "\tWhite: " << edid->white(); } else { qCDebug(KSCREEN_XRANDR) << "\tUnavailable"; } } } void XRandRConfig::printInternalCond() const { qCDebug(KSCREEN_XRANDR) << "Internal config in xrandr"; - Q_FOREACH(XRandROutput *output, m_outputs) { - qCDebug(KSCREEN_XRANDR) << "Id: " << output->id(); - qCDebug(KSCREEN_XRANDR) << "Current Mode: " << output->currentMode(); - qCDebug(KSCREEN_XRANDR) << "Current mode id: " << output->currentModeId(); - qCDebug(KSCREEN_XRANDR) << "Connected: " << output->isConnected(); - qCDebug(KSCREEN_XRANDR) << "Enabled: " << output->isEnabled(); - qCDebug(KSCREEN_XRANDR) << "Primary: " << output->isPrimary(); + for (const XRandROutput *output : m_outputs) { + qCDebug(KSCREEN_XRANDR) << "Id: " << output->id() << "\n" + << "Current Mode: " << output->currentMode() << "\n" + << "Current mode id: " << output->currentModeId() << "\n" + << "Connected: " << output->isConnected() << "\n" + << "Enabled: " << output->isEnabled() << "\n" + << "Primary: " << output->isPrimary(); if (!output->isEnabled()) { continue; } + XRandRMode::Map modes = output->modes(); - Q_FOREACH(XRandRMode *mode, modes) { - qCDebug(KSCREEN_XRANDR) << "\t" << mode->id(); - qCDebug(KSCREEN_XRANDR) << "\t" << mode->name(); - qCDebug(KSCREEN_XRANDR) << "\t" << mode->size() << mode->refreshRate(); + for (const XRandRMode *mode : modes) { + qCDebug(KSCREEN_XRANDR) << "\t" << mode->id() << "\n" + << "\t" << mode->name() << "\n" + << "\t" << mode->size() << mode->refreshRate(); } } } QSize XRandRConfig::screenSize(const KScreen::ConfigPtr &config) const { QRect rect; - Q_FOREACH(const KScreen::OutputPtr &output, config->outputs()) { + for (const KScreen::OutputPtr &output : config->outputs()) { if (!output->isConnected() || !output->isEnabled()) { continue; } const ModePtr currentMode = output->currentMode(); if (!currentMode) { qCDebug(KSCREEN_XRANDR) << "Output: " << output->name() << " has no current Mode!"; continue; } const QRect outputGeom = output->geometry(); rect = rect.united(outputGeom); } const QSize size = QSize(rect.width(), rect.height()); qCDebug(KSCREEN_XRANDR) << "Requested screen size is" << size; return size; } bool XRandRConfig::setScreenSize(const QSize &size) const { - const double dpi = (25.4 * XRandR::screen()->height_in_pixels / XRandR::screen()->height_in_millimeters); - const int widthMM = ((25.4 * size.width()) / dpi); - const int heightMM = ((25.4 * size.height()) / dpi); + const double dpi = 25.4 * XRandR::screen()->height_in_pixels + / XRandR::screen()->height_in_millimeters; + const int widthMM = (25.4 * size.width()) / dpi; + const int heightMM = (25.4 * size.height()) / dpi; - qCDebug(KSCREEN_XRANDR) << "RRSetScreenSize"; - qCDebug(KSCREEN_XRANDR) << "\tDPI:" << dpi; - qCDebug(KSCREEN_XRANDR) << "\tSize:" << size; - qCDebug(KSCREEN_XRANDR) << "\tSizeMM:" << QSize(widthMM, heightMM); + qCDebug(KSCREEN_XRANDR) << "RRSetScreenSize" << "\n" + << "\tDPI:" << dpi << "\n" + << "\tSize:" << size << "\n" + << "\tSizeMM:" << QSize(widthMM, heightMM); xcb_randr_set_screen_size(XCB::connection(), XRandR::rootWindow(), size.width(), size.height(), widthMM, heightMM); m_screen->update(size); return true; } void XRandRConfig::setPrimaryOutput(xcb_randr_output_t outputId) const { - qCDebug(KSCREEN_XRANDR) << "RRSetOutputPrimary"; - qCDebug(KSCREEN_XRANDR) << "\tNew primary:" << outputId; + qCDebug(KSCREEN_XRANDR) << "RRSetOutputPrimary" << "\n" + << "\tNew primary:" << outputId; xcb_randr_set_output_primary(XCB::connection(), XRandR::rootWindow(), outputId); for (XRandROutput *output : m_outputs) { output->setIsPrimary(output->id() == outputId); } } bool XRandRConfig::disableOutput(const OutputPtr &kscreenOutput) const { XRandROutput *xOutput = output(kscreenOutput->id()); Q_ASSERT(xOutput); Q_ASSERT(xOutput->crtc()); + if (!xOutput->crtc()) { qCWarning(KSCREEN_XRANDR) << "Attempting to disable output without CRTC, wth?"; return false; } const xcb_randr_crtc_t crtc = xOutput->crtc()->crtc(); - qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (disable output)"; - qCDebug(KSCREEN_XRANDR) << "\tCRTC:" << crtc; + qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (disable output)" << "\n" + << "\tCRTC:" << crtc; auto cookie = xcb_randr_set_crtc_config(XCB::connection(), crtc, XCB_CURRENT_TIME, XCB_CURRENT_TIME, 0, 0, XCB_NONE, XCB_RANDR_ROTATION_ROTATE_0, 0, nullptr); - XCB::ScopedPointer reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + + XCB::ScopedPointer + reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + if (!reply) { qCDebug(KSCREEN_XRANDR) << "\tResult: unknown (error)"; return false; } qCDebug(KSCREEN_XRANDR) << "\tResult:" << reply->status; // Update the cached output now, otherwise we get RRNotify_CrtcChange notification // for an outdated output, which can lead to a crash. if (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS) { - xOutput->update(XCB_NONE, XCB_NONE, xOutput->isConnected() ? XCB_RANDR_CONNECTION_CONNECTED : XCB_RANDR_CONNECTION_DISCONNECTED, + xOutput->update(XCB_NONE, XCB_NONE, + xOutput->isConnected() ? XCB_RANDR_CONNECTION_CONNECTED : + XCB_RANDR_CONNECTION_DISCONNECTED, kscreenOutput->isPrimary()); } return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); } bool XRandRConfig::enableOutput(const OutputPtr &kscreenOutput) const { xcb_randr_output_t outputs[1] { static_cast(kscreenOutput->id()) }; XRandRCrtc *freeCrtc = nullptr; qCDebug(KSCREEN_XRANDR) << m_crtcs; - Q_FOREACH (XRandRCrtc *crtc, m_crtcs) { + + for (XRandRCrtc *crtc : m_crtcs) { crtc->update(); - qCDebug(KSCREEN_XRANDR) << "Testing CRTC" << crtc->crtc(); - qCDebug(KSCREEN_XRANDR) << "\tFree:" << crtc->isFree(); - qCDebug(KSCREEN_XRANDR) << "\tMode:" << crtc->mode(); - qCDebug(KSCREEN_XRANDR) << "\tPossible outputs:" << crtc->possibleOutputs(); - qCDebug(KSCREEN_XRANDR) << "\tConnected outputs:" << crtc->outputs(); - qCDebug(KSCREEN_XRANDR) << "\tGeometry:" << crtc->geometry(); + qCDebug(KSCREEN_XRANDR) << "Testing CRTC" << crtc->crtc() << "\n" + << "\tFree:" << crtc->isFree() << "\n" + << "\tMode:" << crtc->mode() << "\n" + << "\tPossible outputs:" << crtc->possibleOutputs() << "\n" + << "\tConnected outputs:" << crtc->outputs() << "\n" + << "\tGeometry:" << crtc->geometry(); + if (crtc->isFree() && crtc->possibleOutputs().contains(kscreenOutput->id())) { freeCrtc = crtc; break; } } + if (!freeCrtc) { qCWarning(KSCREEN_XRANDR) << "Failed to get free CRTC for output" << kscreenOutput->id(); return false; } - const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : kscreenOutput->preferredModeId().toInt(); + const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : + kscreenOutput->preferredModeId().toInt(); - qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (enable output)"; - qCDebug(KSCREEN_XRANDR) << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() << ")"; - qCDebug(KSCREEN_XRANDR) << "\tNew CRTC:" << freeCrtc->crtc(); - qCDebug(KSCREEN_XRANDR) << "\tPos:" << kscreenOutput->pos(); - qCDebug(KSCREEN_XRANDR) << "\tMode:" << kscreenOutput->currentMode() << "Preferred:" << kscreenOutput->preferredModeId(); - qCDebug(KSCREEN_XRANDR) << "\tRotation:" << kscreenOutput->rotation(); + qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (enable output)" << "\n" + << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() + << ")" << "\n" + << "\tNew CRTC:" << freeCrtc->crtc() << "\n" + << "\tPos:" << kscreenOutput->pos() << "\n" + << "\tMode:" << kscreenOutput->currentMode() + << "Preferred:" << kscreenOutput->preferredModeId() << "\n" + << "\tRotation:" << kscreenOutput->rotation(); auto cookie = xcb_randr_set_crtc_config(XCB::connection(), freeCrtc->crtc(), XCB_CURRENT_TIME, XCB_CURRENT_TIME, kscreenOutput->pos().rx(), kscreenOutput->pos().ry(), modeId, kscreenOutput->rotation(), 1, outputs); - XCB::ScopedPointer reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + + XCB::ScopedPointer + reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + if (!reply) { qCDebug(KSCREEN_XRANDR) << "Result: unknown (error)"; return false; } qCDebug(KSCREEN_XRANDR) << "\tResult:" << reply->status; if (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS) { XRandROutput *xOutput = output(kscreenOutput->id()); - xOutput->update(freeCrtc->crtc(), modeId, - XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); + xOutput->update(freeCrtc->crtc(), modeId, XCB_RANDR_CONNECTION_CONNECTED, + kscreenOutput->isPrimary()); } return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); } bool XRandRConfig::changeOutput(const OutputPtr &kscreenOutput) const { XRandROutput *xOutput = output(kscreenOutput->id()); Q_ASSERT(xOutput); if (!xOutput->crtc()) { - qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() << "has no CRTC, falling back to enableOutput()"; + qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() + << "has no CRTC, falling back to enableOutput()"; return enableOutput(kscreenOutput); } - int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : kscreenOutput->preferredModeId().toInt(); + int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : + kscreenOutput->preferredModeId().toInt(); - qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)"; - qCDebug(KSCREEN_XRANDR) << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() << ")"; - qCDebug(KSCREEN_XRANDR) << "\tCRTC:" << xOutput->crtc()->crtc(); - qCDebug(KSCREEN_XRANDR) << "\tPos:" << kscreenOutput->pos(); - qCDebug(KSCREEN_XRANDR) << "\tMode:" << modeId << kscreenOutput->currentMode(); - qCDebug(KSCREEN_XRANDR) << "\tRotation:" << kscreenOutput->rotation(); + qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" + << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() + << ")" << "\n" + << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" + << "\tPos:" << kscreenOutput->pos() << "\n" + << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" + << "\tRotation:" << kscreenOutput->rotation(); xcb_randr_output_t outputs[1] { static_cast(kscreenOutput->id()) }; auto cookie = xcb_randr_set_crtc_config(XCB::connection(), xOutput->crtc()->crtc(), XCB_CURRENT_TIME, XCB_CURRENT_TIME, kscreenOutput->pos().rx(), kscreenOutput->pos().ry(), modeId, kscreenOutput->rotation(), 1, outputs); - XCB::ScopedPointer reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + + XCB::ScopedPointer + reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); + if (!reply) { qCDebug(KSCREEN_XRANDR) << "\tResult: unknown (error)"; return false; } qCDebug(KSCREEN_XRANDR) << "\tResult: " << reply->status; if (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS) { xOutput->update(xOutput->crtc()->crtc(), modeId, XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); } return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); } diff --git a/backends/xrandr/xrandrconfig.h b/backends/xrandr/xrandrconfig.h index 3d7ec45..66283de 100644 --- a/backends/xrandr/xrandrconfig.h +++ b/backends/xrandr/xrandrconfig.h @@ -1,75 +1,74 @@ /************************************************************************************* * Copyright 2012, 2013 Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - -#ifndef XRANDRCONFIG_H -#define XRANDRCONFIG_H +#pragma once #include #include "xrandr.h" #include "xrandrcrtc.h" #include "xrandroutput.h" class XRandRScreen; namespace KScreen { class Config; } class XRandRConfig : public QObject { Q_OBJECT public: - explicit XRandRConfig(); + XRandRConfig(); ~XRandRConfig() override; XRandROutput::Map outputs() const; XRandROutput *output(xcb_randr_output_t output) const; XRandRCrtc::Map crtcs() const; XRandRCrtc *crtc(xcb_randr_crtc_t crtc) const; XRandRScreen *screen() const; void addNewOutput(xcb_randr_output_t id); void addNewCrtc(xcb_randr_crtc_t crtc); void removeOutput(xcb_randr_output_t id); KScreen::ConfigPtr toKScreenConfig() const; void applyKScreenConfig(const KScreen::ConfigPtr &config); private: - /** - * We need to print stuff to discover the damn bug - * where currentMode is null - */ - void printConfig(const KScreen::ConfigPtr &config) const; - void printInternalCond() const; QSize screenSize(const KScreen::ConfigPtr &config) const; bool setScreenSize(const QSize &size) const; + void setPrimaryOutput(xcb_randr_output_t outputId) const; + bool disableOutput(const KScreen::OutputPtr &output) const; bool enableOutput(const KScreen::OutputPtr &output) const; bool changeOutput(const KScreen::OutputPtr &output) const; + /** + * We need to print stuff to discover the damn bug + * where currentMode is null + */ + void printConfig(const KScreen::ConfigPtr &config) const; + void printInternalCond() const; + XRandROutput::Map m_outputs; XRandRCrtc::Map m_crtcs; XRandRScreen *m_screen; }; - -#endif // XRANDRCONFIG_H diff --git a/backends/xrandr/xrandrcrtc.cpp b/backends/xrandr/xrandrcrtc.cpp index 4b5ff41..c3f2f00 100644 --- a/backends/xrandr/xrandrcrtc.cpp +++ b/backends/xrandr/xrandrcrtc.cpp @@ -1,123 +1,129 @@ /* * Copyright 2015 Daniel Vrátil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ - #include "xrandrcrtc.h" -#include "xrandrconfig.h" + #include "xrandr.h" +#include "xrandrconfig.h" #include "../xcbwrapper.h" XRandRCrtc::XRandRCrtc(xcb_randr_crtc_t crtc, XRandRConfig *config) : QObject(config) , m_crtc(crtc) , m_mode(0) , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) { update(); } xcb_randr_crtc_t XRandRCrtc::crtc() const { return m_crtc; } xcb_randr_mode_t XRandRCrtc::mode() const { return m_mode; } QRect XRandRCrtc::geometry() const { return m_geometry; } xcb_randr_rotation_t XRandRCrtc::rotation() const { return m_rotation; } QVector XRandRCrtc::possibleOutputs() { return m_possibleOutputs; } QVector XRandRCrtc::outputs() const { return m_outputs; } bool XRandRCrtc::connectOutput(xcb_randr_output_t output) { update(); qCDebug(KSCREEN_XRANDR) << "Connected output" << output << "to CRTC" << m_crtc; + if (!m_possibleOutputs.contains(output)) { - qCDebug(KSCREEN_XRANDR) << "Output" << output << "is not an allowed output for CRTC" << m_crtc; + qCDebug(KSCREEN_XRANDR) << "Output" << output + << "is not an allowed output for CRTC" << m_crtc; return false; } if (!m_outputs.contains(output)) { m_outputs.append(output); } return true; } void XRandRCrtc::disconectOutput(xcb_randr_output_t output) { update(); qCDebug(KSCREEN_XRANDR) << "Disconnected output" << output << "from CRTC" << m_crtc; + const int index = m_outputs.indexOf(output); if (index > -1) { m_outputs.remove(index); } } bool XRandRCrtc::isFree() const { return m_outputs.isEmpty(); } void XRandRCrtc::update() { XCB::CRTCInfo crtcInfo(m_crtc, XCB_TIME_CURRENT_TIME); m_mode = crtcInfo->mode; - m_rotation = (xcb_randr_rotation_t) crtcInfo->rotation; + m_geometry = QRect(crtcInfo->x, crtcInfo->y, crtcInfo->width, crtcInfo->height); + m_rotation = (xcb_randr_rotation_t) crtcInfo->rotation; + m_possibleOutputs.clear(); m_possibleOutputs.reserve(crtcInfo->num_possible_outputs); + xcb_randr_output_t *possible = xcb_randr_get_crtc_info_possible(crtcInfo); for (int i = 0; i < crtcInfo->num_possible_outputs; ++i) { m_possibleOutputs.append(possible[i]); } m_outputs.clear(); xcb_randr_output_t *outputs = xcb_randr_get_crtc_info_outputs(crtcInfo); for (int i = 0; i < crtcInfo->num_outputs; ++i) { m_outputs.append(outputs[i]); } } void XRandRCrtc::update(xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom) { m_mode = mode; - m_rotation = rotation; m_geometry = geom; + m_rotation = rotation; } diff --git a/backends/xrandr/xrandrcrtc.h b/backends/xrandr/xrandrcrtc.h index e08b684..54fb56c 100644 --- a/backends/xrandr/xrandrcrtc.h +++ b/backends/xrandr/xrandrcrtc.h @@ -1,68 +1,68 @@ /* * Copyright 2015 Daniel Vrátil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ +#pragma once -#ifndef XRANDRCRTC_H -#define XRANDRCRTC_H - +#include #include #include #include -#include #include class XRandRConfig; class XRandRCrtc : public QObject { Q_OBJECT public: typedef QMap Map; XRandRCrtc(xcb_randr_crtc_t crtc, XRandRConfig *config); xcb_randr_crtc_t crtc() const; xcb_randr_mode_t mode() const; - xcb_randr_rotation_t rotation() const; + QRect geometry() const; + xcb_randr_rotation_t rotation() const; + QVector possibleOutputs(); QVector outputs() const; bool connectOutput(xcb_randr_output_t output); void disconectOutput(xcb_randr_output_t output); bool isFree() const; void update(); void update(xcb_randr_crtc_t mode, xcb_randr_rotation_t rotation, const QRect &geom); private: xcb_randr_crtc_t m_crtc; xcb_randr_mode_t m_mode; - xcb_randr_rotation_t m_rotation; + QRect m_geometry; + xcb_randr_rotation_t m_rotation; + QVector m_possibleOutputs; QVector m_outputs; }; - -#endif // XRANDRCRTC_H diff --git a/backends/xrandr/xrandrmode.cpp b/backends/xrandr/xrandrmode.cpp index 0f7fca9..d2f24d7 100644 --- a/backends/xrandr/xrandrmode.cpp +++ b/backends/xrandr/xrandrmode.cpp @@ -1,69 +1,69 @@ /************************************************************************************* * Copyright 2012, 2013 Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - #include "xrandrmode.h" -#include "xrandroutput.h" + #include "mode.h" #include "output.h" +#include "xrandroutput.h" XRandRMode::XRandRMode(const xcb_randr_mode_info_t &modeInfo, XRandROutput *output) : QObject(output) { m_id = modeInfo.id; // FIXME XCB //m_name = QString::fromUtf8(modeInfo->name); m_size = QSize(modeInfo.width, modeInfo.height); - m_refreshRate = ((float) modeInfo.dot_clock / ((float) modeInfo.htotal * (float) modeInfo.vtotal)); + m_refreshRate = (float) modeInfo.dot_clock + / ((float) modeInfo.htotal * (float) modeInfo.vtotal); } - XRandRMode::~XRandRMode() { } KScreen::ModePtr XRandRMode::toKScreenMode() { KScreen::ModePtr kscreenMode(new KScreen::Mode); kscreenMode->setId(QString::number(m_id)); kscreenMode->setName(m_name); kscreenMode->setSize(m_size); kscreenMode->setRefreshRate(m_refreshRate); return kscreenMode; } xcb_randr_mode_t XRandRMode::id() const { return m_id; } QSize XRandRMode::size() const { return m_size; } float XRandRMode::refreshRate() const { return m_refreshRate; } QString XRandRMode::name() const { return m_name; } diff --git a/backends/xrandr/xrandrmode.h b/backends/xrandr/xrandrmode.h index 1ed98b9..aed2fea 100644 --- a/backends/xrandr/xrandrmode.h +++ b/backends/xrandr/xrandrmode.h @@ -1,63 +1,59 @@ /************************************************************************************* * Copyright 2012, 2013 Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - -#ifndef XRANDRMODE_H -#define XRANDRMODE_H +#pragma once #include #include #include #include #include "types.h" #include "../xcbwrapper.h" class XRandROutput; namespace KScreen { class Output; class Mode; } class XRandRMode : public QObject { Q_OBJECT public: typedef QMap Map; explicit XRandRMode(const xcb_randr_mode_info_t &modeInfo, XRandROutput *output); ~XRandRMode() override; KScreen::ModePtr toKScreenMode(); xcb_randr_mode_t id() const; QSize size() const; float refreshRate() const; QString name() const; private: xcb_randr_mode_t m_id; QString m_name; QSize m_size; float m_refreshRate; }; Q_DECLARE_METATYPE(XRandRMode::Map) - -#endif // XRANDRMODE_H diff --git a/backends/xrandr/xrandroutput.cpp b/backends/xrandr/xrandroutput.cpp index 8b1bb4a..ef22520 100644 --- a/backends/xrandr/xrandroutput.cpp +++ b/backends/xrandr/xrandroutput.cpp @@ -1,343 +1,349 @@ /************************************************************************************* * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2012, 2013 by Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - #include "xrandroutput.h" -#include "xrandrmode.h" -#include "xrandrconfig.h" -#include "xrandr.h" -#include "output.h" + #include "config.h" +#include "xrandr.h" +#include "xrandrconfig.h" +#include "xrandrmode.h" #include "../utils.h" -#include - Q_DECLARE_METATYPE(QList) XRandROutput::XRandROutput(xcb_randr_output_t id, XRandRConfig *config) : QObject(config) , m_config(config) , m_id(id) - , m_type(KScreen::Output::Unknown) , m_primary(false) + , m_type(KScreen::Output::Unknown) , m_crtc(nullptr) { init(); } XRandROutput::~XRandROutput() { } xcb_randr_output_t XRandROutput::id() const { return m_id; } bool XRandROutput::isConnected() const { return m_connected == XCB_RANDR_CONNECTION_CONNECTED; } bool XRandROutput::isEnabled() const { return m_crtc != nullptr && m_crtc->mode() != XCB_NONE; } bool XRandROutput::isPrimary() const { return m_primary; } QPoint XRandROutput::position() const { return m_crtc ? m_crtc->geometry().topLeft() : QPoint(); } QSize XRandROutput::size() const { return m_crtc ? m_crtc->geometry().size() : QSize(); } XRandRMode::Map XRandROutput::modes() const { return m_modes; } QString XRandROutput::currentModeId() const { return m_crtc ? QString::number(m_crtc->mode()) : QString(); } XRandRMode* XRandROutput::currentMode() const { if (!m_crtc) { return nullptr; } + unsigned int modeId = m_crtc->mode(); if (!m_modes.contains(modeId)) { return nullptr; } return m_modes[modeId]; } KScreen::Output::Rotation XRandROutput::rotation() const { - return static_cast(m_crtc ? m_crtc->rotation() : XCB_RANDR_ROTATION_ROTATE_0); + return static_cast(m_crtc ? m_crtc->rotation() : + XCB_RANDR_ROTATION_ROTATE_0); } QByteArray XRandROutput::edid() const { if (m_edid.isNull()) { m_edid = XRandR::outputEdid(m_id); } return m_edid; } XRandRCrtc* XRandROutput::crtc() const { return m_crtc; } void XRandROutput::update() { init(); } -void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, bool primary) +void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, + bool primary) { - qCDebug(KSCREEN_XRANDR) << "XRandROutput" << m_id << "update"; - qCDebug(KSCREEN_XRANDR) << "\tm_connected:" << m_connected; - qCDebug(KSCREEN_XRANDR) << "\tm_crtc" << m_crtc; - qCDebug(KSCREEN_XRANDR) << "\tCRTC:" << crtc; - qCDebug(KSCREEN_XRANDR) << "\tMODE:" << mode; - qCDebug(KSCREEN_XRANDR) << "\tConnection:" << conn; - qCDebug(KSCREEN_XRANDR) << "\tPrimary:" << primary; + qCDebug(KSCREEN_XRANDR) << "XRandROutput" << m_id << "update" << "\n" + << "\tm_connected:" << m_connected << "\n" + << "\tm_crtc" << m_crtc << "\n" + << "\tCRTC:" << crtc << "\n" + << "\tMODE:" << mode << "\n" + << "\tConnection:" << conn << "\n" + << "\tPrimary:" << primary; // Connected or disconnected if (isConnected() != (conn == XCB_RANDR_CONNECTION_CONNECTED)) { if (conn == XCB_RANDR_CONNECTION_CONNECTED) { // New monitor has been connected, refresh everything init(); } else { // Disconnected m_connected = conn; m_clones.clear(); m_heightMm = 0; m_widthMm = 0; m_type = KScreen::Output::Unknown; qDeleteAll(m_modes); m_modes.clear(); m_preferredModes.clear(); m_edid.clear(); } } else if (conn == XCB_RANDR_CONNECTION_CONNECTED) { // the output changed in some way, let's update the internal // list of modes, as it may have changed XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME); if (outputInfo) { updateModes(outputInfo); } m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); } // A monitor has been enabled or disabled // We don't use isEnabled(), because it checks for crtc && crtc->mode(), however // crtc->mode may already be unset due to xcb_randr_crtc_tChangeNotify coming before // xcb_randr_output_tChangeNotify and reseting the CRTC mode if ((m_crtc == nullptr) != (crtc == XCB_NONE)) { if (crtc == XCB_NONE && mode == XCB_NONE) { // Monitor has been disabled m_crtc->disconectOutput(m_id); m_crtc = nullptr; } else { m_crtc = m_config->crtc(crtc); m_crtc->connectOutput(m_id); } } // Primary has changed m_primary = primary; } void XRandROutput::setIsPrimary(bool primary) { m_primary = primary; } void XRandROutput::init() { XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME); Q_ASSERT(outputInfo); if (!outputInfo) { return; } XCB::PrimaryOutput primary(XRandR::rootWindow()); - m_name = QString::fromUtf8((const char *) xcb_randr_get_output_info_name(outputInfo.data()), outputInfo->name_len); + m_name = QString::fromUtf8((const char *) xcb_randr_get_output_info_name(outputInfo.data()), + outputInfo->name_len); m_type = fetchOutputType(m_id, m_name); m_icon = QString(); m_connected = (xcb_randr_connection_t) outputInfo->connection; m_primary = (primary->output == m_id); + xcb_randr_output_t *clones = xcb_randr_get_output_info_clones(outputInfo.data()); for (int i = 0; i < outputInfo->num_clones; ++i) { m_clones.append(clones[i]); } + m_widthMm = outputInfo->mm_width; m_heightMm = outputInfo->mm_height; + m_crtc = m_config->crtc(outputInfo->crtc); if (m_crtc) { m_crtc->connectOutput(m_id); } m_hotplugModeUpdate = XRandR::hasProperty(m_id, "hotplug_mode_update"); updateModes(outputInfo); } void XRandROutput::updateModes(const XCB::OutputInfo &outputInfo) { /* Init modes */ - XCB::ScopedPointer screenResources(XRandR::screenResources()); + XCB::ScopedPointer + screenResources(XRandR::screenResources()); + Q_ASSERT(screenResources); if (!screenResources) { return; } xcb_randr_mode_info_t *modes = xcb_randr_get_screen_resources_modes(screenResources.data()); xcb_randr_mode_t *outputModes = xcb_randr_get_output_info_modes(outputInfo.data()); m_preferredModes.clear(); qDeleteAll(m_modes); m_modes.clear(); for (int i = 0; i < outputInfo->num_modes; ++i) { /* Resources->modes contains all possible modes, we are only interested * in those listed in outputInfo->modes. */ for (int j = 0; j < screenResources->num_modes; ++j) { if (modes[j].id != outputModes[i]) { continue; } XRandRMode *mode = new XRandRMode(modes[j], this); m_modes.insert(mode->id(), mode); if (i < outputInfo->num_preferred) { m_preferredModes.append(QString::number(mode->id())); } break; } } } -KScreen::Output::Type XRandROutput::fetchOutputType(xcb_randr_output_t outputId, const QString &name) +KScreen::Output::Type XRandROutput::fetchOutputType(xcb_randr_output_t outputId, + const QString &name) { QString type = QString::fromUtf8(typeFromProperty(outputId)); if (type.isEmpty()) { type = name; } return Utils::guessOutputType(type, name); } QByteArray XRandROutput::typeFromProperty(xcb_randr_output_t outputId) { QByteArray type; XCB::InternAtom atomType(true, 13, "ConnectorType"); if (!atomType) { return type; } - char *connectorType; - auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType->atom, XCB_ATOM_ANY, 0, 100, false, false); - XCB::ScopedPointer reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, nullptr)); + XCB::ScopedPointer + reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, nullptr)); if (!reply) { return type; } if (!(reply->type == XCB_ATOM_ATOM && reply->format == 32 && reply->num_items == 1)) { return type; } const uint8_t *prop = xcb_randr_get_output_property_data(reply.data()); XCB::AtomName atomName(*reinterpret_cast(prop)); if (!atomName) { return type; } - connectorType = xcb_get_atom_name_name(atomName); + char *connectorType = xcb_get_atom_name_name(atomName); if (!connectorType) { return type; } type = connectorType; return type; } KScreen::OutputPtr XRandROutput::toKScreenOutput() const { KScreen::OutputPtr kscreenOutput(new KScreen::Output); const bool signalsBlocked = kscreenOutput->signalsBlocked(); kscreenOutput->blockSignals(true); kscreenOutput->setId(m_id); kscreenOutput->setType(m_type); kscreenOutput->setSizeMm(QSize(m_widthMm, m_heightMm)); 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; for (auto iter = m_modes.constBegin(), end = m_modes.constEnd(); iter != end; ++iter) { XRandRMode *mode = iter.value(); kscreenModes.insert(QString::number(iter.key()), mode->toKScreenMode()); } kscreenOutput->setModes(kscreenModes); kscreenOutput->setPreferredModes(m_preferredModes); kscreenOutput->setPrimary(m_primary); kscreenOutput->setClones([](const QList &clones) { QList kclones; kclones.reserve(clones.size()); for (xcb_randr_output_t o : clones) { kclones.append(static_cast(o)); } return kclones; }(m_clones)); kscreenOutput->setEnabled(isEnabled()); if (isEnabled()) { kscreenOutput->setSize(size()); kscreenOutput->setPos(position()); kscreenOutput->setRotation(rotation()); kscreenOutput->setCurrentModeId(currentModeId()); } } kscreenOutput->blockSignals(signalsBlocked); return kscreenOutput; } diff --git a/backends/xrandr/xrandroutput.h b/backends/xrandr/xrandroutput.h index 7b07e88..08c6968 100644 --- a/backends/xrandr/xrandroutput.h +++ b/backends/xrandr/xrandroutput.h @@ -1,98 +1,106 @@ /************************************************************************************* * Copyright 2012, 2013 Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ +#pragma once -#ifndef XRANDROUTPUT_H -#define XRANDROUTPUT_H +#include "output.h" + +#include "xrandrmode.h" +#include "../xcbwrapper.h" #include #include #include -#include "xrandrmode.h" -#include "output.h" -#include "../xcbwrapper.h" - class XRandRConfig; class XRandRCrtc; namespace KScreen { class Config; class Output; } class XRandROutput : public QObject { Q_OBJECT public: typedef QMap Map; explicit XRandROutput(xcb_randr_output_t id, XRandRConfig *config); ~XRandROutput() override; void disabled(); void disconnected(); void update(); - void update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, bool primary); + void update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t conn, + bool primary); void setIsPrimary(bool primary); xcb_randr_output_t id() const; + bool isEnabled() const; bool isConnected() const; bool isPrimary() const; + QPoint position() const; QSize size() const; + QString currentModeId() const; XRandRMode::Map modes() const; XRandRMode* currentMode() const; + KScreen::Output::Rotation rotation() const; bool isHorizontal() const; + QByteArray edid() const; XRandRCrtc* crtc() const; KScreen::OutputPtr toKScreenOutput() const; private: void init(); void updateModes(const XCB::OutputInfo &outputInfo); static KScreen::Output::Type fetchOutputType(xcb_randr_output_t outputId, const QString &name); static QByteArray typeFromProperty(xcb_randr_output_t outputId); XRandRConfig *m_config; xcb_randr_output_t m_id; QString m_name; + QString m_icon; + mutable QByteArray m_edid; + xcb_randr_connection_t m_connected; + bool m_primary; KScreen::Output::Type m_type; - QString m_icon; + XRandRMode::Map m_modes; QStringList m_preferredModes; - bool m_primary; + QList m_clones; - mutable QByteArray m_edid; + unsigned int m_widthMm; unsigned int m_heightMm; + bool m_hotplugModeUpdate = false; XRandRCrtc *m_crtc; }; Q_DECLARE_METATYPE(XRandROutput::Map) - -#endif // XRANDROUTPUT_H diff --git a/backends/xrandr/xrandrscreen.cpp b/backends/xrandr/xrandrscreen.cpp index af36908..9437885 100644 --- a/backends/xrandr/xrandrscreen.cpp +++ b/backends/xrandr/xrandrscreen.cpp @@ -1,75 +1,75 @@ /************************************************************************************* * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2012, 2013 by Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ - #include "xrandrscreen.h" -#include "xrandrconfig.h" -#include "screen.h" + #include "config.h" +#include "screen.h" +#include "xrandrconfig.h" +#include "../xcbwrapper.h" #include -#include "../xcbwrapper.h" - XRandRScreen::XRandRScreen(XRandRConfig *config) : QObject(config) { XCB::ScreenSize size(XRandR::rootWindow()); m_maxSize = QSize(size->max_width, size->max_height); m_minSize = QSize(size->min_width, size->min_height); update(); } XRandRScreen::~XRandRScreen() { } void XRandRScreen::update() { xcb_screen_t *screen = XCB::screenOfDisplay(XCB::connection(), QX11Info::appScreen()); m_currentSize = QSize(screen->width_in_pixels, screen->height_in_pixels); } void XRandRScreen::update(const QSize &size) { m_currentSize = size; } QSize XRandRScreen::currentSize() { return m_currentSize; } KScreen::ScreenPtr XRandRScreen::toKScreenScreen() const { KScreen::ScreenPtr kscreenScreen(new KScreen::Screen); kscreenScreen->setId(m_id); kscreenScreen->setMaxSize(m_maxSize); kscreenScreen->setMinSize(m_minSize); kscreenScreen->setCurrentSize(m_currentSize); - XCB::ScopedPointer screenResources(XRandR::screenResources()); + XCB::ScopedPointer + screenResources(XRandR::screenResources()); kscreenScreen->setMaxActiveOutputsCount(screenResources->num_crtcs); return kscreenScreen; } void XRandRScreen::updateKScreenScreen(KScreen::ScreenPtr &screen) const { screen->setCurrentSize(m_currentSize); } diff --git a/backends/xrandr/xrandrscreen.h b/backends/xrandr/xrandrscreen.h index c2dcde7..2f62f53 100644 --- a/backends/xrandr/xrandrscreen.h +++ b/backends/xrandr/xrandrscreen.h @@ -1,56 +1,52 @@ /************************************************************************************* * Copyright 2012, 2013 Daniel Vrátil * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************************/ +#pragma once -#ifndef XRANDRSCREEN_H -#define XRANDRSCREEN_H +#include "types.h" #include #include -#include "types.h" - class XRandRConfig; namespace KScreen { class Screen; class Config; } class XRandRScreen : public QObject { Q_OBJECT public: explicit XRandRScreen(XRandRConfig *config = nullptr); ~XRandRScreen() override; KScreen::ScreenPtr toKScreenScreen() const; void updateKScreenScreen(KScreen::ScreenPtr &screen) const; void update(); void update(const QSize &size); QSize currentSize(); private: int m_id; QSize m_minSize; QSize m_maxSize; QSize m_currentSize; }; - -#endif // XRANDRSCREEN_H