MythTV master
mythscreensaverx11.cpp
Go to the documentation of this file.
1// Qt
2#include <QDateTime>
3#include <QTimer>
4
5// MythTV
10
13
14// X11 headers
15#include <X11/Xlib.h>
16extern "C" {
17#include <X11/extensions/dpms.h>
18}
19
20#define LOC QString("ScreenSaverX11: ")
21
23{
24 friend class MythScreenSaverX11;
25
26 public:
28 {
31 m_xscreensaverRunning = myth_system("xscreensaver-command -version >&- 2>&-", flags) == 0;
33 {
34 m_resetTimer = new QTimer(Parent);
35 m_resetTimer->setSingleShot(false);
38 LOG(VB_GENERAL, LOG_INFO, LOC + "XScreenSaver support enabled");
39 }
40
42 if (m_display)
43 {
44 int dummy0 = 0;
45 int dummy1 = 0;
46 m_dpmsaware = (DPMSQueryExtension(m_display->GetDisplay(), &dummy0, &dummy1) != 0);
47 }
48 else
49 {
50 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open connection to X11 server");
51 }
52
54 {
55 CARD16 power_level = 0;
56
57 /* If someone runs into X server weirdness that goes away when
58 * they externally disable DPMS, then the 'dpmsenabled' test should
59 * be short circuited by a call to 'DPMSCapable()'. Be sure to
60 * manually initialize dpmsenabled to false.
61 */
62
63 DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
64
65 if (static_cast<bool>(m_dpmsenabled))
66 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
67 else
68 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
69 }
70 else
71 {
72 LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
73 }
74 }
75
77 {
78 // m_resetTimer deleted by ScreenSaverX11 QObject dtor
79 delete m_display;
80 }
81
83 {
85 }
86
87 bool IsDPMSEnabled() const { return static_cast<bool>(m_dpmsenabled); }
88
89 void StopTimer()
90 {
91 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
92 if (m_resetTimer)
93 m_resetTimer->stop();
94 }
95
97 {
98 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
99 if (m_resetTimer)
101 }
102
104 {
105 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
106 StopTimer();
107 // To be clear - this setting has no UI
108 if (m_timeoutInterval == -1s)
109 m_timeoutInterval = gCoreContext->GetDurSetting<std::chrono::seconds>("xscreensaverInterval", 50s);
110 if (m_timeoutInterval > 0s)
111 StartTimer();
112 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
113 }
114
115 // DPMS
116 bool DeactivatedDPMS() const
117 {
118 return m_dpmsdeactivated;
119 }
120
122 {
123 if (IsDPMSEnabled() && m_display)
124 {
125 m_dpmsdeactivated = true;
126 Status status = DPMSDisable(m_display->GetDisplay());
127 m_display->Sync();
128 LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Deactivated %1").arg(status));
129 }
130 }
131
133 {
135 {
136 m_dpmsdeactivated = false;
137 Status status = DPMSEnable(m_display->GetDisplay());
138 m_display->Sync();
139 LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Reactivated %1").arg(status));
140 }
141 }
142
144 {
145 if (!m_state.m_saved && m_display)
146 {
147 XGetScreenSaver(m_display->GetDisplay(), &m_state.m_timeout,
150 m_state.m_saved = true;
151 }
152 }
153
155 {
157 {
158 if (XSetScreenSaver(m_display->GetDisplay(), m_state.m_timeout,
161 {
162 LOG(VB_GENERAL, LOG_INFO, LOC + "Uninhibited screensaver");
163 }
164 else
165 {
166 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to re-enable screensaver");
167 }
168 m_display->Sync();
169 m_state.m_saved = false;
170 }
171 }
172
174 {
176 return;
177
178 QDateTime current_time = MythDate::current();
179 if ((!m_lastDeactivated.isValid()) ||
180 (m_lastDeactivated.secsTo(current_time) > 30))
181 {
183 {
184 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling xscreensaver-command -deactivate");
185 myth_system("xscreensaver-command -deactivate >&- 2>&- &",
187 }
188 m_lastDeactivated = current_time;
189 }
190 }
191
192 private:
194 {
195 public:
196 ScreenSaverState() = default;
197 bool m_saved {false};
198 int m_timeout {-1};
199 int m_interval {-1};
202 };
203
204 private:
205 Q_DISABLE_COPY(ScreenSaverX11Private)
207 bool m_dpmsdeactivated {false};
209 BOOL m_dpmsenabled {static_cast<BOOL>(false)};
210
211 std::chrono::seconds m_timeoutInterval {-1s};
212 QTimer *m_resetTimer {nullptr};
213
215
218};
219
221 : MythScreenSaver(Parent),
222 m_priv(new ScreenSaverX11Private(this))
223{
224}
225
227{
228 // Ensure DPMS gets left as it was found.
229 if (m_priv->DeactivatedDPMS())
231
232 delete m_priv;
233}
234
236{
238
239 if (m_priv->m_display)
240 {
241 int reset = XResetScreenSaver(m_priv->m_display->GetDisplay());
242 int set = XSetScreenSaver(m_priv->m_display->GetDisplay(), 0, 0, 0, 0);
243 if (reset != 1)
244 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to reset screensaver");
245 if (set != 1)
246 LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to disable screensaver");
247 if (reset && set)
248 LOG(VB_GENERAL, LOG_INFO, LOC + "Inhibited X11 screensaver");
250 }
251
253
256}
257
259{
262
263 // One must reset after the restore
264 if (m_priv->m_display)
265 {
266 XResetScreenSaver(m_priv->m_display->GetDisplay());
268 }
269
271 m_priv->StopTimer();
272}
273
275{
276 bool need_xsync = false;
277 Display *dsp = nullptr;
278 if (m_priv->m_display)
279 dsp = m_priv->m_display->GetDisplay();
280
281 if (dsp)
282 {
283 XResetScreenSaver(dsp);
284 need_xsync = true;
285 }
286
288 ResetSlot();
289
290 if (Asleep() && dsp)
291 {
292 DPMSForceLevel(dsp, DPMSModeOn);
293 need_xsync = true;
294 }
295
296 if (need_xsync && m_priv->m_display)
298}
299
301{
302 if (!m_priv->IsDPMSEnabled())
303 return false;
304
305 if (m_priv->DeactivatedDPMS())
306 return false;
307
308 BOOL on = static_cast<BOOL>(false);
309 CARD16 power_level = DPMSModeOn;
310
311 if (m_priv->m_display)
312 DPMSInfo(m_priv->m_display->GetDisplay(), &power_level, &on);
313
314 return (power_level != DPMSModeOn);
315}
316
318{
320}
std::enable_if_t< std::chrono::__is_duration< T >::value, 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:25
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: freesurround.h:24
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
bool
Definition: pxsup2dast.c:31