File indexing completed on 2024-04-28 16:49:43
0001 // SPDX-FileCopyrightText: 2010 by Dario Freddi <drf@kde.org> 0002 // SPDX-FileCopyrightText: 2015 by Kai Uwe Broulik <kde@privat.broulik.de> 0003 // SPDX-FileCopyrightText: 2015 by Martin Gräßlin <mgraesslin@kde.org> 0004 // SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez <aleixpol@kde.org> 0005 // 0006 // SPDX-License-Identifier: LGPL-2.1-or-later 0007 0008 #include "xcbdpmshelper_p.h" 0009 0010 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0011 #include <QX11Info> 0012 #else 0013 #include <private/qtx11extras_p.h> 0014 #endif 0015 #include <QGuiApplication> 0016 0017 #include "kscreendpms_debug.h" 0018 0019 #include <xcb/dpms.h> 0020 0021 template<typename T> 0022 using ScopedCPointer = QScopedPointer<T, QScopedPointerPodDeleter>; 0023 0024 XcbDpmsHelper::XcbDpmsHelper() 0025 : AbstractDpmsHelper() 0026 { 0027 auto *c = QX11Info::connection(); 0028 0029 xcb_prefetch_extension_data(c, &xcb_dpms_id); 0030 auto *extension = xcb_get_extension_data(c, &xcb_dpms_id); 0031 if (!extension || !extension->present) { 0032 qCWarning(KSCREEN_DPMS) << "DPMS extension not available"; 0033 setSupported(false); 0034 return; 0035 } 0036 0037 ScopedCPointer<xcb_dpms_capable_reply_t> capableReply(xcb_dpms_capable_reply(c, xcb_dpms_capable(c), nullptr)); 0038 setSupported(capableReply && capableReply->capable); 0039 0040 // Disable a default timeout, if any 0041 xcb_dpms_set_timeouts(QX11Info::connection(), 0, 0, 0); 0042 } 0043 0044 XcbDpmsHelper::~XcbDpmsHelper() = default; 0045 0046 void XcbDpmsHelper::trigger(KScreen::Dpms::Mode mode, const QList<QScreen *> &screens) 0047 { 0048 setHasPendingChanges(true); 0049 auto *c = QX11Info::connection(); 0050 0051 if (screens != qGuiApp->screens()) { 0052 qCWarning(KSCREEN_DPMS) << "DPMS actions are applied to all screens on X11"; 0053 } 0054 0055 ScopedCPointer<xcb_dpms_info_reply_t> infoReply(xcb_dpms_info_reply(c, xcb_dpms_info(c), nullptr)); 0056 0057 if (!infoReply) { 0058 qCWarning(KSCREEN_DPMS) << "Failed to query DPMS state, cannot trigger"; 0059 return; 0060 } 0061 0062 xcb_dpms_dpms_mode_t level = XCB_DPMS_DPMS_MODE_ON; 0063 switch (mode) { 0064 case KScreen::Dpms::Toggle: 0065 if (infoReply->power_level == XCB_DPMS_DPMS_MODE_ON) { 0066 level = XCB_DPMS_DPMS_MODE_OFF; 0067 } else { 0068 level = XCB_DPMS_DPMS_MODE_ON; 0069 } 0070 break; 0071 case KScreen::Dpms::Off: 0072 level = XCB_DPMS_DPMS_MODE_OFF; 0073 break; 0074 case KScreen::Dpms::Standby: 0075 level = XCB_DPMS_DPMS_MODE_STANDBY; 0076 break; 0077 case KScreen::Dpms::Suspend: 0078 level = XCB_DPMS_DPMS_MODE_SUSPEND; 0079 break; 0080 case KScreen::Dpms::On: 0081 level = XCB_DPMS_DPMS_MODE_ON; 0082 break; 0083 } 0084 0085 if (!infoReply->state) { 0086 xcb_dpms_enable(c); 0087 } 0088 0089 xcb_dpms_force_level(c, level); 0090 0091 setHasPendingChanges(false); 0092 }