powerdevil: use X11 video mode extension as fallback for brightness control

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-06-11 03:15:40 +03:00
parent fcbb39812a
commit 126c0bbd4b
11 changed files with 237 additions and 46 deletions

View file

@ -78,6 +78,7 @@ if(Q_WS_X11)
add_feature_info("libXft" X11_Xft_FOUND "The X11 font API library may be used by kfontinst KCM") add_feature_info("libXft" X11_Xft_FOUND "The X11 font API library may be used by kfontinst KCM")
add_feature_info("libXinerama" X11_Xinerama_FOUND "The X11 XINERAMA extension library may be used by ksplash") add_feature_info("libXinerama" X11_Xinerama_FOUND "The X11 XINERAMA extension library may be used by ksplash")
add_feature_info("libXRes" X11_XRes_FOUND "The X Resource library may be used by ksysguard") add_feature_info("libXRes" X11_XRes_FOUND "The X Resource library may be used by ksysguard")
add_feature_info("libxf86vmode" X11_xf86vmode_FOUND "The X video mode extension library used by powerdevil")
if(NOT X11_Xdamage_FOUND) if(NOT X11_Xdamage_FOUND)
message(FATAL_ERROR "The X11 damaged region extension library was not found. Required for compositing support in KWin.") message(FATAL_ERROR "The X11 damaged region extension library was not found. Required for compositing support in KWin.")

View file

@ -64,6 +64,7 @@ macro_bool_to_01(X11_xf86misc_FOUND HAVE_XF86MISC) # kcontrol/keyboard
macro_bool_to_01(X11_dpms_FOUND HAVE_DPMS) # powerdevil macro_bool_to_01(X11_dpms_FOUND HAVE_DPMS) # powerdevil
macro_bool_to_01(X11_XSync_FOUND HAVE_XSYNC) # kwin macro_bool_to_01(X11_XSync_FOUND HAVE_XSYNC) # kwin
macro_bool_to_01(X11_XRes_FOUND HAVE_XRES) # ksysguard macro_bool_to_01(X11_XRes_FOUND HAVE_XRES) # ksysguard
macro_bool_to_01(X11_xf86vmode_FOUND HAVE_XF86VMODE) # powerdevil
check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker

View file

@ -15,7 +15,7 @@ build_script:
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq cmake katie-dev katanalibs \ sudo apt-get install -qq cmake katie-dev katanalibs \
katana-baseapps xorg-dev libnm-dev libqalculate-dev \ katana-baseapps xorg-dev libnm-dev libqalculate-dev libxxf86vm-dev \
libx11-xcb-dev libxcb-icccm4-dev libxcb-composite0-dev libxcb-damage0-dev \ libx11-xcb-dev libxcb-icccm4-dev libxcb-composite0-dev libxcb-damage0-dev \
libxcb-xfixes0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-shape0-dev \ libxcb-xfixes0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-shape0-dev \
libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-image0-dev \ libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-image0-dev \

View file

@ -39,3 +39,6 @@
/* Define if you have the XRes extension */ /* Define if you have the XRes extension */
#cmakedefine HAVE_XRES 1 #cmakedefine HAVE_XRES 1
/* Define if you have the xf86vmode extension */
#cmakedefine HAVE_XF86VMODE

View file

@ -3,9 +3,15 @@
########################## UPower Backend ##################################### ########################## UPower Backend #####################################
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backends/upower include_directories(
${X11_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/backends/upower
${X11_Xrandr_INCLUDE_PATH}) ${X11_INCLUDE_DIR}
${X11_Xrandr_INCLUDE_PATH}
)
if(X11_xf86vmode_FOUND)
include_directories(${X11_xf86vmode_INCLUDE_PATH})
endif()
set(powerdevilupowerbackend_SRCS set(powerdevilupowerbackend_SRCS
backends/upower/upowersuspendjob.cpp backends/upower/upowersuspendjob.cpp
@ -34,6 +40,11 @@ upower_kbdbacklight_interface)
set(powerdevilupowerbackend_LIBS ${X11_LIBRARIES} ${QT_QTGUI_LIBRARY} ${X11_Xrandr_LIB} ${KDE4_KDEUI_LIBS}) set(powerdevilupowerbackend_LIBS ${X11_LIBRARIES} ${QT_QTGUI_LIBRARY} ${X11_Xrandr_LIB} ${KDE4_KDEUI_LIBS})
if(X11_xf86vmode_FOUND)
set(powerdevilupowerbackend_SRCS ${powerdevilupowerbackend_SRCS} backends/upower/xf86vmodegamma.cpp)
set(powerdevilupowerbackend_LIBS ${X11_Xxf86vm_LIB} ${X11_Xrandr_LIB})
endif()
########################## Daemon variables ################################ ########################## Daemon variables ################################
set(POWERDEVIL_BACKEND_SRCS ${powerdevilupowerbackend_SRCS}) set(POWERDEVIL_BACKEND_SRCS ${powerdevilupowerbackend_SRCS})

View file

@ -37,6 +37,10 @@
#include "upowersuspendjob.h" #include "upowersuspendjob.h"
#include "login1suspendjob.h" #include "login1suspendjob.h"
#ifdef HAVE_XF86VMODE
#include "xf86vmodegamma.h"
#endif
bool checkSystemdVersion(uint requiredVersion) bool checkSystemdVersion(uint requiredVersion)
{ {
@ -57,8 +61,11 @@ bool checkSystemdVersion(uint requiredVersion)
PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent) PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent)
: BackendInterface(parent), : BackendInterface(parent),
m_brightnessControl(0), m_kbdMaxBrightness(0), m_brightnessControl(0), m_randrHelper(0),
m_lidIsPresent(false), m_lidIsClosed(false), m_onBattery(false) #ifdef HAVE_XF86VMODE
m_gammaControl(0),
#endif
m_kbdMaxBrightness(0), m_lidIsPresent(false), m_lidIsClosed(false), m_onBattery(false)
{ {
} }
@ -66,6 +73,9 @@ PowerDevilUPowerBackend::PowerDevilUPowerBackend(QObject* parent)
PowerDevilUPowerBackend::~PowerDevilUPowerBackend() PowerDevilUPowerBackend::~PowerDevilUPowerBackend()
{ {
delete m_brightnessControl; delete m_brightnessControl;
#ifdef HAVE_XF86VMODE
delete m_gammaControl;
#endif
} }
bool PowerDevilUPowerBackend::isAvailable() bool PowerDevilUPowerBackend::isAvailable()
@ -151,6 +161,16 @@ void PowerDevilUPowerBackend::init()
screenBrightnessAvailable = true; screenBrightnessAvailable = true;
} }
#ifdef HAVE_XF86VMODE
if (!m_brightnessControl->isSupported()) {
m_gammaControl = new XF86VModeGamma();
if (m_gammaControl->isSupported()) {
kDebug() << "Using X Video Mode";
screenBrightnessAvailable = true;
}
}
#endif
// Capabilities // Capabilities
setCapabilities(SignalResumeFromSuspend); setCapabilities(SignalResumeFromSuspend);
@ -306,9 +326,15 @@ float PowerDevilUPowerBackend::brightness(PowerDevil::BackendInterface::Brightne
if (type == Screen) { if (type == Screen) {
if (m_brightnessControl->isSupported()) { if (m_brightnessControl->isSupported()) {
//kDebug() << "Calling xrandr brightness"; kDebug() << "Calling XRandr brightness";
result = m_brightnessControl->brightness(); result = m_brightnessControl->brightness();
} }
#ifdef HAVE_XF86VMODE
else if (m_gammaControl->isSupported()) {
kDebug() << "Calling XF86VidMode gamma";
result = m_gammaControl->gamma();
}
#endif
kDebug() << "Screen brightness: " << result; kDebug() << "Screen brightness: " << result;
} else if (type == Keyboard) { } else if (type == Keyboard) {
kDebug() << "Kbd backlight brightness: " << m_kbdBacklight->GetBrightness(); kDebug() << "Kbd backlight brightness: " << m_kbdBacklight->GetBrightness();
@ -326,6 +352,11 @@ bool PowerDevilUPowerBackend::setBrightness(float brightnessValue, PowerDevil::B
if (m_brightnessControl->isSupported()) { if (m_brightnessControl->isSupported()) {
m_brightnessControl->setBrightness(brightnessValue); m_brightnessControl->setBrightness(brightnessValue);
success = true; success = true;
#ifdef HAVE_XF86VMODE
} else if (m_gammaControl->isSupported()) {
m_gammaControl->setGamma(brightnessValue);
success = true;
#endif
} else { } else {
success = false; success = false;
} }

View file

@ -22,6 +22,8 @@
#ifndef POWERDEVILUPOWERBACKEND_H #ifndef POWERDEVILUPOWERBACKEND_H
#define POWERDEVILUPOWERBACKEND_H #define POWERDEVILUPOWERBACKEND_H
#include <config-X11.h>
#include <powerdevilbackendinterface.h> #include <powerdevilbackendinterface.h>
#include <QtDBus/QDBusConnection> #include <QtDBus/QDBusConnection>
@ -44,6 +46,7 @@
class UdevHelper; class UdevHelper;
class XRandRX11Helper; class XRandRX11Helper;
class XRandrBrightness; class XRandrBrightness;
class XF86VModeGamma;
class KDE_EXPORT PowerDevilUPowerBackend : public PowerDevil::BackendInterface class KDE_EXPORT PowerDevilUPowerBackend : public PowerDevil::BackendInterface
{ {
@ -88,6 +91,9 @@ private:
QMap<BrightnessControlType, float> m_cachedBrightnessMap; QMap<BrightnessControlType, float> m_cachedBrightnessMap;
XRandrBrightness *m_brightnessControl; XRandrBrightness *m_brightnessControl;
XRandRX11Helper *m_randrHelper; XRandRX11Helper *m_randrHelper;
#ifdef HAVE_XF86VMODE
XF86VModeGamma *m_gammaControl;
#endif
OrgFreedesktopUPowerInterface *m_upowerInterface; OrgFreedesktopUPowerInterface *m_upowerInterface;
OrgFreedesktopUPowerKbdBacklightInterface *m_kbdBacklight; OrgFreedesktopUPowerKbdBacklightInterface *m_kbdBacklight;

View file

@ -0,0 +1,108 @@
/* This file is part of the KDE project
* Copyright (C) 2021 Ivailo Monev <xakepa10@gmail.com>
*
* 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 <kdebug.h>
#include "xf86vmodegamma.h"
#include <config-X11.h>
#include <string.h>
// for reference:
// https://cgit.freedesktop.org/xorg/app/xgamma/plain/xgamma.c
// 50 means normal screen gamma, anything lower than that should make it darker
// and higher should make it brighter
static const float xgammaratio = 50.0;
XF86VModeGamma::XF86VModeGamma()
: m_supported(false)
{
int majorversion, minorversion;
if (!XF86VidModeQueryVersion(m_x11info.display(), &majorversion, &minorversion)) {
kWarning() << "XF86VidMode version query failed";
return;
}
int eventbase, errorbase;
if (!XF86VidModeQueryExtension(m_x11info.display(), &eventbase, &errorbase)) {
kWarning() << "XF86VidMode extension missing";
return;
}
Q_UNUSED(eventbase);
Q_UNUSED(errorbase);
// same version requirement as xgamma application
if (majorversion < 2) {
kWarning() << "XF86VidMode version too old" << majorversion << minorversion;
return;
}
m_supported = true;
}
XF86VModeGamma::~XF86VModeGamma()
{
}
bool XF86VModeGamma::isSupported() const
{
return m_supported;
}
float XF86VModeGamma::gamma() const
{
float result = 0;
if (!m_supported) {
return result;
}
XF86VidModeGamma xgamma;
if (!XF86VidModeGetGamma(m_x11info.display(), m_x11info.screen(), &xgamma)) {
kWarning() << "Could not query gamma via XF86VidMode";
return result;
}
// result should be in the [0-100] range
result = (xgammaratio * xgamma.red * xgamma.green * xgamma.blue);
return result;
}
void XF86VModeGamma::setGamma(float gamma)
{
if (!m_supported) {
return;
}
XF86VidModeGamma xgamma;
// in case new member is added
::memset(&xgamma, 0, sizeof(XF86VidModeGamma));
// values should be in the [0.1-10.0] range
xgamma.red = (gamma / xgammaratio);
xgamma.green = (gamma / xgammaratio);
xgamma.blue = (gamma / xgammaratio);
if (!XF86VidModeSetGamma(m_x11info.display(), m_x11info.screen(), &xgamma)) {
kWarning() << "Could not set gamma via XF86VidMode";
return;
}
XSync(m_x11info.display(), False);
}

View file

@ -0,0 +1,43 @@
/* This file is part of the KDE project
* Copyright (C) 2021 Ivailo Monev <xakepa10@gmail.com>
*
* 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 XF86VMODEGAMMA_H
#define XF86VMODEGAMMA_H
#include <QtGui/qx11info_x11.h>
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
#include <fixx11h.h>
class XF86VModeGamma
{
public:
XF86VModeGamma();
~XF86VModeGamma();
bool isSupported() const;
float gamma() const;
void setGamma(float gamma);
private:
bool m_supported;
QX11Info m_x11info;
};
#endif // XF86VMODEGAMMA_H

View file

@ -23,11 +23,7 @@ extern "C"
{ {
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#define INT8 _X11INT8
#define INT32 _X11INT32
#include <X11/Xproto.h> #include <X11/Xproto.h>
#undef INT8
#undef INT32
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
} }

View file

@ -17,13 +17,14 @@
* *
*/ */
#include <kdebug.h>
#include "xrandrbrightness.h" #include "xrandrbrightness.h"
#include <config-X11.h> #include <config-X11.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -33,15 +34,13 @@ XRandrBrightness::XRandrBrightness()
{ {
// init // init
int major, minor; int major, minor;
if (!XRRQueryVersion (QX11Info::display(), &major, &minor)) if (!XRRQueryVersion (QX11Info::display(), &major, &minor)) {
{ kWarning() << "RandR extension missing";
qWarning("RandR extension missing");
return; return;
} }
if (major < 1 || (major == 1 && minor < 2)) if (major < 1 || (major == 1 && minor < 2)) {
{ kWarning() << "RandR version %d.%d too old" << major << minor;
qWarning("RandR version %d.%d too old", major, minor);
return; return;
} }
@ -49,17 +48,15 @@ XRandrBrightness::XRandrBrightness()
if (m_backlight == None) if (m_backlight == None)
m_backlight = XInternAtom(QX11Info::display(), "BACKLIGHT", True); // try with legacy atom m_backlight = XInternAtom(QX11Info::display(), "BACKLIGHT", True); // try with legacy atom
if (m_backlight == None) if (m_backlight == None) {
{ kWarning() << "No outputs have backlight property";
qWarning("No outputs have backlight property");
return; return;
} }
m_resources = XRRGetScreenResources(QX11Info::display(), QX11Info::appRootWindow()); m_resources = XRRGetScreenResources(QX11Info::display(), QX11Info::appRootWindow());
if (!m_resources) if (!m_resources) {
{ kWarning() << "No available Randr resources";
qWarning("No available Randr resources");
return; return;
} }
} }
@ -77,8 +74,7 @@ bool XRandrBrightness::isSupported() const
return false; return false;
// Verify that there are outputs that actually support backlight control... // Verify that there are outputs that actually support backlight control...
for (int o = 0; o < m_resources->noutput; o++) for (int o = 0; o < m_resources->noutput; o++) {
{
if (backlight_get(m_resources->outputs[o]) != -1) { if (backlight_get(m_resources->outputs[o]) != -1) {
return true; return true;
} }
@ -91,20 +87,17 @@ float XRandrBrightness::brightness() const
{ {
float result = 0; float result = 0;
if (!m_resources) if (!m_resources) {
return result; return result;
}
for (int o = 0; o < m_resources->noutput; o++) for (int o = 0; o < m_resources->noutput; o++) {
{
RROutput output = m_resources->outputs[o]; RROutput output = m_resources->outputs[o];
double cur = backlight_get(output); double cur = backlight_get(output);
if (cur != -1) if (cur != -1) {
{
XRRPropertyInfo * info = XRRQueryOutputProperty(QX11Info::display(), output, m_backlight); XRRPropertyInfo * info = XRRQueryOutputProperty(QX11Info::display(), output, m_backlight);
if (info) if (info) {
{ if (info->range && info->num_values == 2) {
if (info->range && info->num_values == 2)
{
double min = info->values[0]; double min = info->values[0];
double max = info->values[1]; double max = info->values[1];
XFree(info); XFree(info);
@ -126,17 +119,13 @@ void XRandrBrightness::setBrightness(float brightness)
if (!m_resources) if (!m_resources)
return; return;
for (int o = 0; o < m_resources->noutput; o++) for (int o = 0; o < m_resources->noutput; o++) {
{
RROutput output = m_resources->outputs[o]; RROutput output = m_resources->outputs[o];
double cur = backlight_get(output); double cur = backlight_get(output);
if (cur != -1) if (cur != -1) {
{
XRRPropertyInfo * info = XRRQueryOutputProperty(QX11Info::display(), output, m_backlight); XRRPropertyInfo * info = XRRQueryOutputProperty(QX11Info::display(), output, m_backlight);
if (info) if (info) {
{ if (info->range && info->num_values == 2) {
if (info->range && info->num_values == 2)
{
double min = info->values[0]; double min = info->values[0];
double max = info->values[1]; double max = info->values[1];
@ -164,13 +153,15 @@ long XRandrBrightness::backlight_get(RROutput output) const
if (!m_backlight || XRRGetOutputProperty (QX11Info::display(), output, m_backlight, if (!m_backlight || XRRGetOutputProperty (QX11Info::display(), output, m_backlight,
0, 4, False, False, None, 0, 4, False, False, None,
&actual_type, &actual_format, &actual_type, &actual_format,
&nitems, &bytes_after, &prop) != Success) &nitems, &bytes_after, &prop) != Success) {
return -1; return -1;
}
if (actual_type != XA_INTEGER || nitems != 1 || actual_format != 32) if (actual_type != XA_INTEGER || nitems != 1 || actual_format != 32) {
value = -1; value = -1;
else } else {
value = *((long *) prop); value = *((long *) prop);
}
XFree (prop); XFree (prop);
return value; return value;
} }