MythTV master
mythscreensaverx11.cpp
Go to the documentation of this file.
1// Qt
2#include <QChar> // Fix Qt6 GCC SFINAE warning
3#include <QDateTime>
4#include <QTimer>
5
6// MythTV
11
14
15// X11 headers
16#if defined(_X11_XLIB_H_) && !defined(Bool)
17#define Bool int
18#endif
19#include <X11/Xlib.h>
20extern "C" {
21#include <X11/extensions/dpms.h>
22}
23#undef Bool // Interferes with moc file compilation
24
25#define LOC QString("ScreenSaverX11: ")
26
28{
29 friend class MythScreenSaverX11;
30
31 public:
33 {
36 m_xscreensaverRunning = myth_system("xscreensaver-command -version >&- 2>&-", flags) == 0;
38 {
39 m_resetTimer = new QTimer(Parent);
40 m_resetTimer->setSingleShot(false);
43 LOG(VB_GENERAL, LOG_INFO, LOC + "XScreenSaver support enabled");
44 }
45
47 if (m_display)
48 {
49 int dummy0 = 0;
50 int dummy1 = 0;
51 m_dpmsaware = (DPMSQueryExtension(m_display->GetDisplay(), &dummy0, &dummy1) != 0);
52 }
53 else
54 {
55 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open connection to X11 server");
56 }
57
59 {
60 CARD16 power_level = 0;
61
62 /* If someone runs into X server weirdness that goes away when
63 * they externally disable DPMS, then the 'dpmsenabled' test should
64 * be short circuited by a call to 'DPMSCapable()'. Be sure to
65 * manually initialize dpmsenabled to false.
66 */
67
68 DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
69
70 if (static_cast<bool>(m_dpmsenabled))
71 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
72 else
73 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
74 }
75 else
76 {
77 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
78 }
79 }
80
82 {
83 // m_resetTimer deleted by ScreenSaverX11 QObject dtor
84 delete m_display;
85 }
86
88 {
90 }
91
92 bool IsDPMSEnabled() const { return static_cast<bool>(m_dpmsenabled); }
93
94 void StopTimer()
95 {
96 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
97 if (m_resetTimer)
98 m_resetTimer->stop();
99 }
100
102 {
103 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
104 if (m_resetTimer)
106 }
107
109 {
110 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
111 StopTimer();
112 // To be clear - this setting has no UI
113 if (m_timeoutInterval == -1s)
114 m_timeoutInterval = gCoreContext->GetDurSetting<std::chrono::seconds>("xscreensaverInterval", 50s);
115 if (m_timeoutInterval > 0s)
116 StartTimer();
117 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
118 }
119
120 // DPMS
121 bool DeactivatedDPMS() const
122 {
123 return m_dpmsdeactivated;
124 }
125
127 {
128 if (IsDPMSEnabled() && m_display)
129 {
130 m_dpmsdeactivated = true;
131 Status status = DPMSDisable(m_display->GetDisplay());
132 m_display->Sync();
133 LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Deactivated %1").arg(status));
134 }
135 }
136
138 {
140 {
141 m_dpmsdeactivated = false;
142 Status status = DPMSEnable(m_display->GetDisplay());
143 m_display->Sync();
144 LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Reactivated %1").arg(status));
145 }
146 }
147
149 {
150 if (!m_state.m_saved && m_display)
151 {
152 XGetScreenSaver(m_display->GetDisplay(), &m_state.m_timeout,
155 m_state.m_saved = true;
156 }
157 }
158
160 {
162 {
163 if (XSetScreenSaver(m_display->GetDisplay(), m_state.m_timeout,
166 {
167 LOG(VB_GENERAL, LOG_INFO, LOC + "Uninhibited screensaver");
168 }
169 else
170 {
171 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to re-enable screensaver");
172 }
173 m_display->Sync();
174 m_state.m_saved = false;
175 }
176 }
177
179 {
181 return;
182
183 QDateTime current_time = MythDate::current();
184 if ((!m_lastDeactivated.isValid()) ||
185 (m_lastDeactivated.secsTo(current_time) > 30))
186 {
188 {
189 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling xscreensaver-command -deactivate");
190 myth_system("xscreensaver-command -deactivate >&- 2>&- &",
192 }
193 m_lastDeactivated = current_time;
194 }
195 }
196
197 private:
199 {
200 public:
201 ScreenSaverState() = default;
202 bool m_saved {false};
203 int m_timeout {-1};
204 int m_interval {-1};
207 };
208
209 private:
210 Q_DISABLE_COPY(ScreenSaverX11Private)
211 bool m_dpmsaware {false};
212 bool m_dpmsdeactivated {false};
214 BOOL m_dpmsenabled {static_cast<BOOL>(false)};
215
216 std::chrono::seconds m_timeoutInterval {-1s};
217 QTimer *m_resetTimer {nullptr};
218
220
223};
224
226 : MythScreenSaver(Parent),
227 m_priv(new ScreenSaverX11Private(this))
228{
229}
230
232{
233 // Ensure DPMS gets left as it was found.
234 if (m_priv->DeactivatedDPMS())
236
237 delete m_priv;
238}
239
241{
243
244 if (m_priv->m_display)
245 {
246 int reset = XResetScreenSaver(m_priv->m_display->GetDisplay());
247 int set = XSetScreenSaver(m_priv->m_display->GetDisplay(), 0, 0, 0, 0);
248 if (reset != 1)
249 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to reset screensaver");
250 if (set != 1)
251 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to disable screensaver");
252 if (reset && set)
253 LOG(VB_GENERAL, LOG_INFO, LOC + "Inhibited X11 screensaver");
255 }
256
258
261}
262
264{
267
268 // One must reset after the restore
269 if (m_priv->m_display)
270 {
271 XResetScreenSaver(m_priv->m_display->GetDisplay());
273 }
274
276 m_priv->StopTimer();
277}
278
280{
281 bool need_xsync = false;
282 Display *dsp = nullptr;
283 if (m_priv->m_display)
284 dsp = m_priv->m_display->GetDisplay();
285
286 if (dsp)
287 {
288 XResetScreenSaver(dsp);
289 need_xsync = true;
290 }
291
293 ResetSlot();
294
295 if (Asleep() && dsp)
296 {
297 DPMSForceLevel(dsp, DPMSModeOn);
298 need_xsync = true;
299 }
300
301 if (need_xsync && m_priv->m_display)
303}
304
306{
307 if (!m_priv->IsDPMSEnabled())
308 return false;
309
310 if (m_priv->DeactivatedDPMS())
311 return false;
312
313 BOOL on = static_cast<BOOL>(false);
314 CARD16 power_level = DPMSModeOn;
315
316 if (m_priv->m_display)
317 DPMSInfo(m_priv->m_display->GetDisplay(), &power_level, &on);
318
319 return (power_level != DPMSModeOn);
320}
321
323{
325}
326
327#include "moc_mythscreensaverx11.cpp"
T GetDurSetting(const QString &key, T defaultval=T::zero())
MythScreenSaverX11(QObject *Parent)
class ScreenSaverX11Private * m_priv
Base Class for screensavers.
void Sync(bool Flush=false)
Display * GetDisplay()
Definition: mythxdisplay.h:28
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
std::chrono::seconds m_timeoutInterval
bool m_dpmsdeactivated
true if we disabled DPMS
ScreenSaverX11Private(MythScreenSaverX11 *Parent)
unsigned int uint
Definition: compat.h:60
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
@ kMSRunBackground
run child in the background
Definition: mythsystem.h:38
@ kMSDontDisableDrawing
avoid disabling UI drawing
Definition: mythsystem.h:37
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15