[powerdevil/Plasma/5.14] /: Revert "Remove XRandrBrightness"
Kai Uwe Broulik
null at kde.org
Tue Sep 25 14:58:43 BST 2018
Git commit 6b93d74675aeb8f6fad26f62f300e4ed6b155ad4 by Kai Uwe Broulik.
Committed on 25/09/2018 at 13:57.
Pushed by broulik into branch 'Plasma/5.14'.
Revert "Remove XRandrBrightness"
Apparently there's still graphics cards that rely on this :'(
This was the only real change in this cycle, so just reverting it is safe,
albeit technically being a dependency change.
BUG: 399018
CCMAIL: kde-distro-packagers at kde.org
This reverts commit 7e29869329184d9e2bae6019939e2ecb0eceac0d.
M +1 -1 CMakeLists.txt
M +6 -1 daemon/backends/CMakeLists.txt
M +113 -59 daemon/backends/upower/powerdevilupowerbackend.cpp
M +4 -0 daemon/backends/upower/powerdevilupowerbackend.h
A +221 -0 daemon/backends/upower/xrandrbrightness.cpp [License: LGPL (v2)]
A +51 -0 daemon/backends/upower/xrandrbrightness.h [License: LGPL (v2)]
A +124 -0 daemon/backends/upower/xrandrxcbhelper.cpp [License: GPL (v2+)]
A +99 -0 daemon/backends/upower/xrandrxcbhelper.h [License: GPL (v2+)]
https://commits.kde.org/powerdevil/6b93d74675aeb8f6fad26f62f300e4ed6b155ad4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d73ce4..2782a09 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,7 +54,7 @@ find_package(LibKWorkspace ${PROJECT_VERSION} REQUIRED)
find_package(UDev REQUIRED)
-find_package(XCB REQUIRED COMPONENTS XCB DPMS)
+find_package(XCB REQUIRED COMPONENTS XCB RANDR DPMS)
option(WITH_DDCUTIL "DDCUtil library support" OFF)
if(WITH_DDCUTIL)
diff --git a/daemon/backends/CMakeLists.txt b/daemon/backends/CMakeLists.txt
index 2dc465a..8c5e203 100644
--- a/daemon/backends/CMakeLists.txt
+++ b/daemon/backends/CMakeLists.txt
@@ -1,12 +1,15 @@
########################## UPower Backend #####################################
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/upower
- ${X11_INCLUDE_DIR})
+ ${X11_INCLUDE_DIR}
+ ${X11_Xrandr_INCLUDE_PATH})
set(powerdevilupowerbackend_SRCS
${PowerDevil_SOURCE_DIR}/daemon/powerdevil_debug.cpp
upower/upowersuspendjob.cpp
upower/login1suspendjob.cpp
upower/powerdevilupowerbackend.cpp
+ upower/xrandrbrightness.cpp
+ upower/xrandrxcbhelper.cpp
upower/udevqtclient.cpp
upower/udevqtdevice.cpp
upower/ddcutilbrightness.cpp
@@ -54,7 +57,9 @@ target_link_libraries(powerdevilupowerbackend
KF5::I18n
${UDEV_LIBS}
${X11_LIBRARIES}
+ ${X11_Xrandr_LIB}
${XCB_XCB_LIBRARY}
+ ${XCB_RANDR_LIBRARY}
powerdevilcore
)
if(DDCUTIL_FOUND)
diff --git a/daemon/backends/upower/powerdevilupowerbackend.cpp b/daemon/backends/upower/powerdevilupowerbackend.cpp
index 454ba69..7af7059 100644
--- a/daemon/backends/upower/powerdevilupowerbackend.cpp
+++ b/daemon/backends/upower/powerdevilupowerbackend.cpp
@@ -36,6 +36,8 @@
#include <KSharedConfig>
#include <KAuthAction>
+#include "xrandrxcbhelper.h"
+#include "xrandrbrightness.h"
#include "ddcutilbrightness.h"
#include "upowersuspendjob.h"
#include "login1suspendjob.h"
@@ -46,6 +48,8 @@
PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent)
: BackendInterface(parent)
, m_displayDevice(nullptr)
+ , m_brightnessControl(nullptr)
+ , m_randrHelper(nullptr)
, m_upowerInterface(nullptr)
, m_kbdBacklight(nullptr)
, m_kbdMaxBrightness(0)
@@ -57,7 +61,10 @@ PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent)
}
-PowerDevilUPowerBackend::~PowerDevilUPowerBackend() = default;
+PowerDevilUPowerBackend::~PowerDevilUPowerBackend()
+{
+ delete m_brightnessControl;
+}
bool PowerDevilUPowerBackend::isAvailable()
{
@@ -144,66 +151,90 @@ void PowerDevilUPowerBackend::init()
connect(this, &PowerDevilUPowerBackend::brightnessSupportQueried, this, &PowerDevilUPowerBackend::initWithBrightness);
m_upowerInterface = new OrgFreedesktopUPowerInterface(UPOWER_SERVICE, "/org/freedesktop/UPower", QDBusConnection::systemBus(), this);
- m_ddcBrightnessControl = new DDCutilBrightness();
- m_ddcBrightnessControl->detect();
- if (!m_ddcBrightnessControl->isSupported()) {
- qCDebug(POWERDEVIL) << "Falling back to helper to get brightness";
-
- KAuth::Action brightnessAction("org.kde.powerdevil.backlighthelper.brightness");
- brightnessAction.setHelperId(HELPER_ID);
- KAuth::ExecuteJob *brightnessJob = brightnessAction.execute();
- connect(brightnessJob, &KJob::result, this, [this, brightnessJob] {
- if (brightnessJob->error()) {
- qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightness failed";
- qCDebug(POWERDEVIL) << brightnessJob->errorText();
- Q_EMIT brightnessSupportQueried(false);
- return;
- }
- m_cachedBrightnessMap.insert(Screen, brightnessJob->data()["brightness"].toFloat());
-
- KAuth::Action brightnessMaxAction("org.kde.powerdevil.backlighthelper.brightnessmax");
- brightnessMaxAction.setHelperId(HELPER_ID);
- KAuth::ExecuteJob *brightnessMaxJob = brightnessMaxAction.execute();
- connect(brightnessMaxJob, &KJob::result, this,
- [this, brightnessMaxJob] {
- if (brightnessMaxJob->error()) {
- qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightnessmax failed";
- qCDebug(POWERDEVIL) << brightnessMaxJob->errorText();
- } else {
- m_brightnessMax = brightnessMaxJob->data()["brightnessmax"].toInt();
+ m_brightnessControl = new XRandrBrightness();
+ if (!m_brightnessControl->isSupported()) {
+ qCWarning(POWERDEVIL)<<"Xrandr not supported, trying ddc, helper";
+ m_ddcBrightnessControl = new DDCutilBrightness();
+ m_ddcBrightnessControl->detect();
+ if (!m_ddcBrightnessControl->isSupported()) {
+ qCDebug(POWERDEVIL) << "Falling back to helper to get brightness";
+
+ KAuth::Action brightnessAction("org.kde.powerdevil.backlighthelper.brightness");
+ brightnessAction.setHelperId(HELPER_ID);
+ KAuth::ExecuteJob *brightnessJob = brightnessAction.execute();
+ connect(brightnessJob, &KJob::result, this,
+ [this, brightnessJob] {
+ if (brightnessJob->error()) {
+ qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightness failed";
+ qCDebug(POWERDEVIL) << brightnessJob->errorText();
+ Q_EMIT brightnessSupportQueried(false);
+ return;
}
-
- KAuth::Action syspathAction("org.kde.powerdevil.backlighthelper.syspath");
- syspathAction.setHelperId(HELPER_ID);
- KAuth::ExecuteJob* syspathJob = syspathAction.execute();
- connect(syspathJob, &KJob::result, this,
- [this, syspathJob] {
- if (syspathJob->error()) {
- qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.syspath failed";
- qCDebug(POWERDEVIL) << syspathJob->errorText();
- Q_EMIT brightnessSupportQueried(false);
- return;
+ m_cachedBrightnessMap.insert(Screen, brightnessJob->data()["brightness"].toFloat());
+
+ KAuth::Action brightnessMaxAction("org.kde.powerdevil.backlighthelper.brightnessmax");
+ brightnessMaxAction.setHelperId(HELPER_ID);
+ KAuth::ExecuteJob *brightnessMaxJob = brightnessMaxAction.execute();
+ connect(brightnessMaxJob, &KJob::result, this,
+ [this, brightnessMaxJob] {
+ if (brightnessMaxJob->error()) {
+ qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightnessmax failed";
+ qCDebug(POWERDEVIL) << brightnessMaxJob->errorText();
+ } else {
+ m_brightnessMax = brightnessMaxJob->data()["brightnessmax"].toInt();
}
- m_syspath = syspathJob->data()["syspath"].toString();
- m_syspath = QFileInfo(m_syspath).readLink();
- m_isLedBrightnessControl = m_syspath.contains(QLatin1String("/leds/"));
- if (!m_isLedBrightnessControl) {
- UdevQt::Client *client = new UdevQt::Client(QStringList("backlight"), this);
- connect(client, SIGNAL(deviceChanged(UdevQt::Device)), SLOT(onDeviceChanged(UdevQt::Device)));
- }
-
- Q_EMIT brightnessSupportQueried(m_brightnessMax > 0);
+ KAuth::Action syspathAction("org.kde.powerdevil.backlighthelper.syspath");
+ syspathAction.setHelperId(HELPER_ID);
+ KAuth::ExecuteJob* syspathJob = syspathAction.execute();
+ connect(syspathJob, &KJob::result, this,
+ [this, syspathJob] {
+ if (syspathJob->error()) {
+ qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.syspath failed";
+ qCDebug(POWERDEVIL) << syspathJob->errorText();
+ Q_EMIT brightnessSupportQueried(false);
+ return;
+ }
+ m_syspath = syspathJob->data()["syspath"].toString();
+ m_syspath = QFileInfo(m_syspath).readLink();
+
+ m_isLedBrightnessControl = m_syspath.contains(QLatin1String("/leds/"));
+ if (!m_isLedBrightnessControl) {
+ UdevQt::Client *client = new UdevQt::Client(QStringList("backlight"), this);
+ connect(client, SIGNAL(deviceChanged(UdevQt::Device)), SLOT(onDeviceChanged(UdevQt::Device)));
+ }
+
+ Q_EMIT brightnessSupportQueried(m_brightnessMax > 0);
+ }
+ );
+ syspathJob->start();
}
);
- syspathJob->start();
+ brightnessMaxJob->start();
}
);
- brightnessMaxJob->start();
- });
- brightnessJob->start();
+ brightnessJob->start();
+ }
+ else{
+ qCDebug(POWERDEVIL) << "Using DDCutillib";
+ m_cachedBrightnessMap.insert(Screen, brightness(Screen));
+
+ const int duration = PowerDevilSettings::brightnessAnimationDuration();
+ if (duration > 0 && brightnessMax() >= PowerDevilSettings::brightnessAnimationThreshold()) {
+ m_brightnessAnimation = new QPropertyAnimation(this);
+ m_brightnessAnimation->setTargetObject(this);
+ m_brightnessAnimation->setDuration(duration);
+ m_brightnessAnimation->setEasingCurve(QEasingCurve::InOutQuad);
+ connect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &PowerDevilUPowerBackend::animationValueChanged);
+ connect(m_brightnessAnimation, &QPropertyAnimation::finished, this, &PowerDevilUPowerBackend::slotScreenBrightnessChanged);
+ }
+ Q_EMIT brightnessSupportQueried(true);
+ }
} else {
- qCDebug(POWERDEVIL) << "Using DDCutillib";
+ qCDebug(POWERDEVIL) << "Using XRandR";
+ m_randrHelper = XRandRXCBHelper::self();
+ Q_ASSERT(m_randrHelper);
+ connect(m_randrHelper, &XRandRXCBHelper::brightnessChanged, this, &PowerDevilUPowerBackend::slotScreenBrightnessChanged);
m_cachedBrightnessMap.insert(Screen, brightness(Screen));
const int duration = PowerDevilSettings::brightnessAnimationDuration();
@@ -381,13 +412,20 @@ int PowerDevilUPowerBackend::brightness(PowerDevil::BackendInterface::Brightness
int result = 0;
if (type == Screen) {
- if (m_ddcBrightnessControl->isSupported()){
+ if (m_brightnessControl->isSupported()) {
+ if (m_brightnessAnimation && m_brightnessAnimation->state() == QPropertyAnimation::Running) {
+ result = m_brightnessAnimation->endValue().toInt();
+ } else {
+ //qCDebug(POWERDEVIL) << "Calling xrandr brightness";
+ result = (int) m_brightnessControl->brightness();
+ }
+ } else if (m_ddcBrightnessControl->isSupported()){
if (m_brightnessAnimation && m_brightnessAnimation->state() == QPropertyAnimation::Running) {
result = m_brightnessAnimation->endValue().toInt();
} else {
result = (int)m_ddcBrightnessControl->brightness();
}
- } else {
+ }else{
result = m_cachedBrightnessMap[Screen];
}
qCDebug(POWERDEVIL) << "Screen brightness value: " << result;
@@ -404,9 +442,12 @@ int PowerDevilUPowerBackend::brightnessMax(PowerDevil::BackendInterface::Brightn
int result = 0;
if (type == Screen) {
- if (m_ddcBrightnessControl->isSupported()){
+ if (m_brightnessControl->isSupported()) {
+ //qCDebug(POWERDEVIL) << "Calling xrandr brightness";
+ result = (int) m_brightnessControl->brightnessMax();
+ } else if (m_ddcBrightnessControl->isSupported()){
result = (int)m_ddcBrightnessControl->brightnessMax();
- } else {
+ }else{
result = m_brightnessMax;
}
qCDebug(POWERDEVIL) << "Screen brightness value max: " << result;
@@ -422,7 +463,18 @@ void PowerDevilUPowerBackend::setBrightness(int value, PowerDevil::BackendInterf
{
if (type == Screen) {
qCDebug(POWERDEVIL) << "set screen brightness value: " << value;
- if (m_ddcBrightnessControl->isSupported()){
+ if (m_brightnessControl->isSupported()) {
+ if (m_brightnessAnimation) {
+ m_brightnessAnimation->stop();
+ disconnect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &PowerDevilUPowerBackend::animationValueChanged);
+ m_brightnessAnimation->setStartValue(brightness());
+ m_brightnessAnimation->setEndValue(value);
+ connect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &PowerDevilUPowerBackend::animationValueChanged);
+ m_brightnessAnimation->start();
+ } else {
+ m_brightnessControl->setBrightness(value);
+ }
+ } else if (m_ddcBrightnessControl->isSupported()){
if (m_brightnessAnimation) {
m_brightnessAnimation->stop();
disconnect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &PowerDevilUPowerBackend::animationValueChanged);
@@ -661,7 +713,9 @@ void PowerDevilUPowerBackend::slotLogin1PrepareForSleep(bool active)
void PowerDevilUPowerBackend::animationValueChanged(const QVariant &value)
{
- if (m_ddcBrightnessControl->isSupported()) {
+ if (m_brightnessControl->isSupported()) {
+ m_brightnessControl->setBrightness(value.toInt());
+ }else if (m_ddcBrightnessControl->isSupported()) {
m_ddcBrightnessControl->setBrightness(value.toInt());
}
else{
diff --git a/daemon/backends/upower/powerdevilupowerbackend.h b/daemon/backends/upower/powerdevilupowerbackend.h
index cdddbf9..bf90097 100644
--- a/daemon/backends/upower/powerdevilupowerbackend.h
+++ b/daemon/backends/upower/powerdevilupowerbackend.h
@@ -42,6 +42,8 @@
#define CONSOLEKIT2_SERVICE "org.freedesktop.ConsoleKit"
class UdevHelper;
+class XRandRXCBHelper;
+class XRandrBrightness;
class QPropertyAnimation;
class DDCutilBrightness;
class Q_DECL_EXPORT PowerDevilUPowerBackend : public PowerDevil::BackendInterface
@@ -97,6 +99,8 @@ private:
// brightness
QMap<BrightnessControlType, int> m_cachedBrightnessMap;
+ XRandrBrightness *m_brightnessControl;
+ XRandRXCBHelper *m_randrHelper;
DDCutilBrightness *m_ddcBrightnessControl;
OrgFreedesktopUPowerInterface *m_upowerInterface;
diff --git a/daemon/backends/upower/xrandrbrightness.cpp b/daemon/backends/upower/xrandrbrightness.cpp
new file mode 100644
index 0000000..586801c
--- /dev/null
+++ b/daemon/backends/upower/xrandrbrightness.cpp
@@ -0,0 +1,221 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2010 Lukas Tinkl <ltinkl at redhat.com>
+ * Copyright (C) 2015 Kai Uwe Broulik <kde at privat.broulik.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <powerdevil_debug.h>
+
+#include <QX11Info>
+
+#include "xrandrbrightness.h"
+
+XRandrBrightness::XRandrBrightness()
+{
+ if (!QX11Info::isPlatformX11()) {
+ return;
+ }
+
+ auto *c = QX11Info::connection();
+
+ xcb_prefetch_extension_data(c, &xcb_randr_id);
+ // this reply, for once, does not need to be managed by us
+ auto *extension = xcb_get_extension_data(c, &xcb_randr_id);
+ if (!extension || !extension->present) {
+ qCWarning(POWERDEVIL) << "XRandR extension not available";
+ return;
+ }
+
+ ScopedCPointer<xcb_randr_query_version_reply_t> versionReply(xcb_randr_query_version_reply(c,
+ xcb_randr_query_version(c, 1, 2),
+ nullptr));
+
+ if (!versionReply) {
+ qCWarning(POWERDEVIL) << "RandR Query version returned null";
+ return;
+ }
+
+ if (versionReply->major_version < 1 || (versionReply->major_version == 1 && versionReply->minor_version < 2)) {
+ qCWarning(POWERDEVIL, "RandR version %d.%d too old", versionReply->major_version, versionReply->minor_version);
+ return;
+ }
+
+ ScopedCPointer<xcb_intern_atom_reply_t> backlightReply(xcb_intern_atom_reply(c,
+ xcb_intern_atom(c, 1, strlen("Backlight"), "Backlight"),
+ nullptr));
+
+ if (!backlightReply) {
+ qCWarning(POWERDEVIL, "Intern Atom for Backlight returned null");
+ return;
+ }
+
+ m_backlight = backlightReply->atom;
+
+ if (m_backlight == XCB_NONE) {
+ qCWarning(POWERDEVIL, "No outputs have backlight property");
+ return;
+ }
+
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(c));
+ if (!iter.rem) {
+ qCWarning(POWERDEVIL, "XCB Screen Roots Iterator rem was null");
+ return;
+ }
+
+ xcb_screen_t *screen = iter.data;
+ xcb_window_t root = screen->root;
+
+ m_resources.reset(xcb_randr_get_screen_resources_current_reply(c,
+ xcb_randr_get_screen_resources_current(c, root)
+ , nullptr));
+
+ if (!m_resources) {
+ qCWarning(POWERDEVIL, "RANDR Get Screen Resources returned null");
+ return;
+ }
+}
+
+bool XRandrBrightness::isSupported() const
+{
+ if (!m_resources) {
+ return false;
+ }
+
+ auto *outputs = xcb_randr_get_screen_resources_current_outputs(m_resources.data());
+ for (int i = 0; i < m_resources->num_outputs; ++i) {
+ if (backlight_get(outputs[i]) != -1) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+long XRandrBrightness::brightness() const
+{
+ if (!m_resources) {
+ return 0;
+ }
+
+ auto *outputs = xcb_randr_get_screen_resources_current_outputs(m_resources.data());
+ for (int i = 0; i < m_resources->num_outputs; ++i) {
+ auto output = outputs[i];
+
+ long cur, min, max;
+ if (backlight_get_with_range(output, cur, min, max)) {
+ // FIXME for now just return the first output's value
+ return cur - min;
+ }
+ }
+
+ return 0;
+}
+
+long XRandrBrightness::brightnessMax() const
+{
+ if (!m_resources) {
+ return 0;
+ }
+
+ auto *outputs = xcb_randr_get_screen_resources_current_outputs(m_resources.data());
+ for (int i = 0; i < m_resources->num_outputs; ++i) {
+ auto output = outputs[i];
+
+ long cur, min, max;
+ if (backlight_get_with_range(output, cur, min, max)) {
+ // FIXME for now just return the first output's value
+ return max - min;
+ }
+ }
+
+ return 0;
+}
+
+void XRandrBrightness::setBrightness(long value)
+{
+ if (!m_resources) {
+ return;
+ }
+
+ auto *outputs = xcb_randr_get_screen_resources_current_outputs(m_resources.data());
+ for (int i = 0; i < m_resources->num_outputs; ++i) {
+ auto output = outputs[i];
+
+ long cur, min, max;
+ if (backlight_get_with_range(output, cur, min, max)) {
+ // FIXME for now just set the first output's value
+ backlight_set(output, min + value);
+ }
+ }
+
+ free(xcb_get_input_focus_reply(QX11Info::connection(), xcb_get_input_focus(QX11Info::connection()), nullptr)); // sync
+}
+
+bool XRandrBrightness::backlight_get_with_range(xcb_randr_output_t output, long &value, long &min, long &max) const {
+ long cur = backlight_get(output);
+ if (cur == -1) {
+ return false;
+ }
+
+ ScopedCPointer<xcb_randr_query_output_property_reply_t> propertyReply(xcb_randr_query_output_property_reply(QX11Info::connection(),
+ xcb_randr_query_output_property(QX11Info::connection(), output, m_backlight)
+ , nullptr));
+
+ if (!propertyReply) {
+ return -1;
+ }
+
+ if (propertyReply->range && xcb_randr_query_output_property_valid_values_length(propertyReply.data()) == 2) {
+ int32_t *values = xcb_randr_query_output_property_valid_values(propertyReply.data());
+ value = cur;
+ min = values[0];
+ max = values[1];
+ return true;
+ }
+
+ return false;
+}
+
+long XRandrBrightness::backlight_get(xcb_randr_output_t output) const
+{
+ ScopedCPointer<xcb_randr_get_output_property_reply_t> propertyReply;
+ long value;
+
+ if (m_backlight != XCB_ATOM_NONE) {
+ propertyReply.reset(xcb_randr_get_output_property_reply(QX11Info::connection(),
+ xcb_randr_get_output_property(QX11Info::connection(), output, m_backlight, XCB_ATOM_NONE, 0, 4, 0, 0)
+ , nullptr));
+
+ if (!propertyReply) {
+ return -1;
+ }
+ }
+
+ if (!propertyReply || propertyReply->type != XCB_ATOM_INTEGER || propertyReply->num_items != 1 || propertyReply->format != 32) {
+ value = -1;
+ } else {
+ value = *(reinterpret_cast<long *>(xcb_randr_get_output_property_data(propertyReply.data())));
+ }
+ return value;
+}
+
+void XRandrBrightness::backlight_set(xcb_randr_output_t output, long value)
+{
+ xcb_randr_change_output_property(QX11Info::connection(), output, m_backlight, XCB_ATOM_INTEGER,
+ 32, XCB_PROP_MODE_REPLACE,
+ 1, reinterpret_cast<unsigned char *>(&value));
+}
diff --git a/daemon/backends/upower/xrandrbrightness.h b/daemon/backends/upower/xrandrbrightness.h
new file mode 100644
index 0000000..67d44a8
--- /dev/null
+++ b/daemon/backends/upower/xrandrbrightness.h
@@ -0,0 +1,51 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2010 Lukas Tinkl <ltinkl at redhat.com>
+ * Copyright (C) 2015 Kai Uwe Broulik <kde at privat.broulik.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef XRANDRBRIGHTNESS_H
+#define XRANDRBRIGHTNESS_H
+
+#include <xcb/xcb.h>
+#include <xcb/randr.h>
+
+#include <QScopedPointer>
+
+template <typename T> using ScopedCPointer = QScopedPointer<T, QScopedPointerPodDeleter>;
+
+class XRandrBrightness
+{
+public:
+ XRandrBrightness();
+ ~XRandrBrightness() = default;
+ bool isSupported() const;
+ long brightness() const;
+ long brightnessMax() const;
+ void setBrightness(long value);
+
+private:
+ bool backlight_get_with_range(xcb_randr_output_t output, long &value, long &min, long &max) const;
+ long backlight_get(xcb_randr_output_t output) const;
+ void backlight_set(xcb_randr_output_t output, long value);
+
+ xcb_atom_t m_backlight = XCB_ATOM_NONE;
+ ScopedCPointer<xcb_randr_get_screen_resources_current_reply_t> m_resources;
+
+};
+
+#endif // XRANDRBRIGHTNESS_H
diff --git a/daemon/backends/upower/xrandrxcbhelper.cpp b/daemon/backends/upower/xrandrxcbhelper.cpp
new file mode 100644
index 0000000..ee8c2fe
--- /dev/null
+++ b/daemon/backends/upower/xrandrxcbhelper.cpp
@@ -0,0 +1,124 @@
+/*************************************************************************************
+ * Copyright (C) 2013 by Alejandro Fiestas Olivares <afiestas at kde.org> *
+ * *
+ * 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) any later version. *
+ * *
+ * 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, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
+ *************************************************************************************/
+
+#include "xrandrxcbhelper.h"
+
+#include <xcb/randr.h>
+#include <QCoreApplication>
+#include <QLatin1String>
+
+bool XRandRXCBHelper::s_init = false;
+XRandRInfo XRandRXCBHelper::s_xrandrInfo;
+
+XRandRXCBHelper::XRandRXCBHelper() : QObject()
+ , m_window(0)
+{
+ if (!s_init) {
+ init();
+ }
+}
+
+XRandRXCBHelper::~XRandRXCBHelper()
+{
+ xcb_destroy_window(conn(), m_window);
+}
+
+bool XRandRXCBHelper::nativeEventFilter(const QByteArray& eventType, void* message, long int* result)
+{
+ Q_UNUSED(result);
+
+ if (eventType != "xcb_generic_event_t") {
+ return false;
+ }
+
+ xcb_generic_event_t* e = static_cast<xcb_generic_event_t *>(message);
+ const uint8_t xEventType = e->response_type & ~0x80;
+
+ //If this event is not xcb_randr_notify, we don't want it
+ if (xEventType != s_xrandrInfo.eventType) {
+ return false;
+ }
+
+ xcb_randr_notify_event_t*
+ randrEvent = reinterpret_cast<xcb_randr_notify_event_t*>(e);
+
+ //If the event is not about a change in an output property, we don't want it
+ if (randrEvent->subCode != XCB_RANDR_NOTIFY_OUTPUT_PROPERTY) {
+ return false;
+ }
+
+ //If the event is not about a new value, we don't want it
+ if (randrEvent->u.op.status != XCB_PROPERTY_NEW_VALUE) {
+ return false;
+ }
+
+ //If the modified property is not backlight, we don't care
+ if (randrEvent->u.op.atom != s_xrandrInfo.backlightAtom) {
+ return false;
+ }
+
+ Q_EMIT brightnessChanged();
+
+ return false;
+}
+
+void XRandRXCBHelper::init()
+{
+ xcb_connection_t* c = conn();
+
+ xcb_prefetch_extension_data(c, &xcb_randr_id);
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(c, &xcb_randr_id);
+ if (!reply) {
+ s_xrandrInfo.isPresent = false;
+ return;
+ }
+
+ s_xrandrInfo.isPresent = reply->present;
+ s_xrandrInfo.eventBase = reply->first_event;
+ s_xrandrInfo.errorBase = reply->first_error;
+ s_xrandrInfo.eventType = s_xrandrInfo.eventBase + XCB_RANDR_NOTIFY;
+ s_xrandrInfo.majorOpcode = reply->major_opcode;
+
+ QByteArray backlight = QByteArrayLiteral("Backlight");
+
+ /*This is KDE5... the world of opengl and wayland (almost), I don't think we really need to
+ check the old BACKLIGHT atom*/
+// QByteArray backlightCaps("BACKLIGHT");
+// xcb_intern_atom(c, true, backlightCaps.length(), backlightCaps.constData());
+ xcb_intern_atom_reply_t* atomReply =
+ xcb_intern_atom_reply(c, xcb_intern_atom(c, true, backlight.length(), backlight.constData()), nullptr);
+
+ //If backlight atom doesn't exist, means that no driver is actually supporting it
+ if (!atomReply) {
+ return;
+ }
+
+ s_xrandrInfo.backlightAtom = atomReply->atom;
+
+ uint32_t rWindow = rootWindow(c, 0);
+ m_window = xcb_generate_id(c);
+ xcb_create_window(c, XCB_COPY_FROM_PARENT, m_window,
+ rWindow,
+ 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT,
+ XCB_COPY_FROM_PARENT, 0, nullptr);
+
+ xcb_randr_select_input(c, m_window, XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
+ qApp->installNativeEventFilter(this);
+
+ s_init = true;
+}
diff --git a/daemon/backends/upower/xrandrxcbhelper.h b/daemon/backends/upower/xrandrxcbhelper.h
new file mode 100644
index 0000000..ce0e129
--- /dev/null
+++ b/daemon/backends/upower/xrandrxcbhelper.h
@@ -0,0 +1,99 @@
+/*************************************************************************************
+ * Copyright (C) 2013 by Alejandro Fiestas Olivares <afiestas at kde.org> *
+ * *
+ * 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) any later version. *
+ * *
+ * 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, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
+ *************************************************************************************/
+
+#ifndef XRANDR_XCB_HELPER_H
+#define XRANDR_XCB_HELPER_H
+
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#include <QX11Info>
+#include <QObject>
+#include <QAbstractNativeEventFilter>
+
+class XRandRInfo
+{
+public:
+ int version;
+ int eventBase;
+ int errorBase;
+ int majorOpcode;
+ int eventType;
+ xcb_atom_t backlightAtom;
+ bool isPresent;
+};
+
+class XRandRXCBHelper : public QObject, public QAbstractNativeEventFilter
+{
+ Q_OBJECT
+public:
+ static inline XRandRXCBHelper* self()
+ {
+ static XRandRXCBHelper* s_instance = nullptr;
+ if (!s_instance) {
+ s_instance = new XRandRXCBHelper();
+ if (!s_instance->isValid()) {
+ s_instance = nullptr;
+ }
+ }
+
+ return s_instance;
+ }
+
+ bool nativeEventFilter(const QByteArray& eventType, void* message, long int* result) override;
+
+Q_SIGNALS:
+ void brightnessChanged();
+
+private:
+ XRandRXCBHelper();
+ ~XRandRXCBHelper() override;
+ void init();
+
+ inline bool isValid()
+ {
+ return s_xrandrInfo.isPresent;
+ }
+
+ inline xcb_connection_t *conn()
+ {
+ static xcb_connection_t *s_con = nullptr;
+ if (!s_con) {
+ s_con = QX11Info::connection();
+ }
+ return s_con;
+ }
+
+ inline xcb_window_t rootWindow(xcb_connection_t *c, int screen)
+ {
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(c));
+ for (xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(c));
+ it.rem;
+ --screen, xcb_screen_next(&it)) {
+ if (screen == 0) {
+ return iter.data->root;
+ }
+ }
+ return XCB_WINDOW_NONE;
+ }
+
+ uint32_t m_window;
+ static bool s_init;
+ static XRandRInfo s_xrandrInfo;
+};
+
+#endif //XRANDR_XCB_HELPER_H
More information about the Distributions
mailing list