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 }