File indexing completed on 2024-05-12 05:33:54
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 #include <QGuiApplication> 0011 #include <QtGui/private/qtx11extras_p.h> 0012 0013 #include <kscreendpms_debug.h> 0014 0015 #include <xcb/dpms.h> 0016 0017 template<typename T> 0018 using ScopedCPointer = QScopedPointer<T, QScopedPointerPodDeleter>; 0019 0020 XcbDpmsHelper::XcbDpmsHelper() 0021 : AbstractDpmsHelper() 0022 { 0023 auto *c = QX11Info::connection(); 0024 0025 xcb_prefetch_extension_data(c, &xcb_dpms_id); 0026 auto *extension = xcb_get_extension_data(c, &xcb_dpms_id); 0027 if (!extension || !extension->present) { 0028 qCWarning(KSCREEN_DPMS) << "DPMS extension not available"; 0029 setSupported(false); 0030 return; 0031 } 0032 0033 ScopedCPointer<xcb_dpms_capable_reply_t> capableReply(xcb_dpms_capable_reply(c, xcb_dpms_capable(c), nullptr)); 0034 setSupported(capableReply && capableReply->capable); 0035 0036 // Disable a default timeout, if any 0037 xcb_dpms_set_timeouts(QX11Info::connection(), 0, 0, 0); 0038 } 0039 0040 XcbDpmsHelper::~XcbDpmsHelper() = default; 0041 0042 void XcbDpmsHelper::trigger(KScreen::Dpms::Mode mode, const QList<QScreen *> &screens) 0043 { 0044 setHasPendingChanges(true); 0045 auto *c = QX11Info::connection(); 0046 0047 if (screens != qGuiApp->screens()) { 0048 qCWarning(KSCREEN_DPMS) << "DPMS actions are applied to all screens on X11"; 0049 } 0050 0051 ScopedCPointer<xcb_dpms_info_reply_t> infoReply(xcb_dpms_info_reply(c, xcb_dpms_info(c), nullptr)); 0052 0053 if (!infoReply) { 0054 qCWarning(KSCREEN_DPMS) << "Failed to query DPMS state, cannot trigger"; 0055 return; 0056 } 0057 0058 xcb_dpms_dpms_mode_t level = XCB_DPMS_DPMS_MODE_ON; 0059 switch (mode) { 0060 case KScreen::Dpms::Toggle: 0061 if (infoReply->power_level == XCB_DPMS_DPMS_MODE_ON) { 0062 level = XCB_DPMS_DPMS_MODE_OFF; 0063 } else { 0064 level = XCB_DPMS_DPMS_MODE_ON; 0065 } 0066 break; 0067 case KScreen::Dpms::Off: 0068 level = XCB_DPMS_DPMS_MODE_OFF; 0069 break; 0070 case KScreen::Dpms::Standby: 0071 level = XCB_DPMS_DPMS_MODE_STANDBY; 0072 break; 0073 case KScreen::Dpms::Suspend: 0074 level = XCB_DPMS_DPMS_MODE_SUSPEND; 0075 break; 0076 case KScreen::Dpms::On: 0077 level = XCB_DPMS_DPMS_MODE_ON; 0078 break; 0079 } 0080 0081 if (!infoReply->state) { 0082 xcb_dpms_enable(c); 0083 } 0084 0085 xcb_dpms_force_level(c, level); 0086 0087 setHasPendingChanges(false); 0088 }