MythTV  master
screensaver-x11.cpp
Go to the documentation of this file.
1 // Own header
2 #include "screensaver-x11.h"
3 
4 // QT headers
5 #include <QDateTime>
6 #include <QTimer>
7 
8 // Mythdb headers
9 #include "mythlogging.h"
10 #include "mythdate.h"
11 #include "mythdb.h"
12 
13 // Mythui headers
14 #include "mythsystemlegacy.h"
15 #include "mythxdisplay.h"
16 
17 // X11 headers
18 #include <X11/Xlib.h>
19 
20 extern "C" {
21 #include <X11/extensions/dpms.h>
22 }
23 
24 #define LOC QString("ScreenSaverX11Private: ")
25 
27 {
28  friend class ScreenSaverX11;
29 
30  public:
32  {
36  myth_system("xscreensaver-command -version >&- 2>&-",
37  flags) == 0;
38 
40  {
41  m_resetTimer = new QTimer(outer);
42  m_resetTimer->setSingleShot(false);
43  QObject::connect(m_resetTimer, SIGNAL(timeout()),
44  outer, SLOT(resetSlot()));
46  LOG(VB_GENERAL, LOG_INFO, LOC + "XScreenSaver support enabled");
47  }
48 
50  if (m_display)
51  {
52  int dummy0 = 0;
53  int dummy1 = 0;
54  m_dpmsaware = DPMSQueryExtension(m_display->GetDisplay(),
55  &dummy0, &dummy1);
56  }
57  else
58  {
59  LOG(VB_GENERAL, LOG_ERR, LOC +
60  "Failed to open connection to X11 server");
61  }
62 
63  if (m_dpmsaware)
64  {
65  CARD16 power_level = 0;
66 
67  /* If someone runs into X server weirdness that goes away when
68  * they externally disable DPMS, then the 'dpmsenabled' test should
69  * be short circuited by a call to 'DPMSCapable()'. Be sure to
70  * manually initialize dpmsenabled to false.
71  */
72 
73  DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
74 
75  if (m_dpmsenabled)
76  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
77  else
78  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
79  }
80  else
81  {
82  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
83  }
84  }
85 
87  {
88  // m_resetTimer deleted by ScreenSaverX11 QObject dtor
89  delete m_display;
90  }
91 
92  bool IsScreenSaverRunning(void) const
93  {
94  return m_xscreensaverRunning;
95  }
96 
97  bool IsDPMSEnabled(void) const { return m_dpmsenabled; }
98 
99  void StopTimer(void)
100  {
101  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
102  if (m_resetTimer)
103  m_resetTimer->stop();
104  }
105 
106  void StartTimer(void)
107  {
108  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
109  if (m_resetTimer)
111  }
112 
113  void ResetTimer(void)
114  {
115  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
116 
117  StopTimer();
118 
119  if (m_timeoutInterval == -1)
120  {
122  "xscreensaverInterval", GetMythDB()->GetHostName(), 50) * 1000;
123  }
124 
125  if (m_timeoutInterval > 0)
126  StartTimer();
127 
128  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
129  }
130 
131  // DPMS
132  bool DeactivatedDPMS(void) const
133  {
134  return m_dpmsdeactivated;
135  }
136 
137  void DisableDPMS(void)
138  {
139  if (IsDPMSEnabled() && m_display)
140  {
141  m_dpmsdeactivated = true;
142  Status status = DPMSDisable(m_display->GetDisplay());
143  m_display->Sync();
144  LOG(VB_GENERAL, LOG_INFO, LOC +
145  QString("DPMS Deactivated %1").arg(status));
146  }
147  }
148 
149  void RestoreDPMS(void)
150  {
152  {
153  m_dpmsdeactivated = false;
154  Status status = DPMSEnable(m_display->GetDisplay());
155  m_display->Sync();
156  LOG(VB_GENERAL, LOG_INFO, LOC +
157  QString("DPMS Reactivated %1").arg(status));
158  }
159  }
160 
161  void SaveScreenSaver(void)
162  {
163  if (!m_state.m_saved && m_display)
164  {
165  XGetScreenSaver(m_display->GetDisplay(), &m_state.m_timeout,
168  m_state.m_saved = true;
169  }
170  }
171 
173  {
174  if (m_state.m_saved && m_display)
175  {
176  XSetScreenSaver(m_display->GetDisplay(), m_state.m_timeout,
179  m_display->Sync();
180  m_state.m_saved = false;
181  }
182  }
183 
184  void ResetScreenSaver(void)
185  {
186  if (!IsScreenSaverRunning())
187  return;
188 
189  QDateTime current_time = MythDate::current();
190  if ((!m_lastDeactivated.isValid()) ||
191  (m_lastDeactivated.secsTo(current_time) > 30))
192  {
194  {
195  LOG(VB_PLAYBACK, LOG_INFO, LOC +
196  "Calling xscreensaver-command -deactivate");
197  myth_system("xscreensaver-command -deactivate >&- 2>&- &",
201  }
202  m_lastDeactivated = current_time;
203  }
204  }
205 
206  private:
208  {
209  public:
210  ScreenSaverState() = default;
211  bool m_saved {false};
212  int m_timeout {-1};
213  int m_interval {-1};
214  int m_preferblank {-1};
215  int m_allowexposure {-1};
216  };
217 
218  private:
219  bool m_dpmsaware {false};
220  bool m_dpmsdeactivated {false};
221  bool m_xscreensaverRunning {false};
222  BOOL m_dpmsenabled {false};
223 
225  QTimer *m_resetTimer {nullptr};
226 
227  QDateTime m_lastDeactivated;
228 
231 };
232 
234  d(new ScreenSaverX11Private(this))
235 {
236 }
237 
239 {
240  /* Ensure DPMS gets left as it was found. */
241  if (d->DeactivatedDPMS())
243 
244  delete d;
245 }
246 
248 {
249  d->SaveScreenSaver();
250 
251  if (d->m_display)
252  {
253  XResetScreenSaver(d->m_display->GetDisplay());
254  XSetScreenSaver(d->m_display->GetDisplay(), 0, 0, 0, 0);
255  d->m_display->Sync();
256  }
257 
258  d->DisableDPMS();
259 
260  if (d->IsScreenSaverRunning())
261  d->ResetTimer();
262 }
263 
265 {
267  d->RestoreDPMS();
268 
269  // One must reset after the restore
270  if (d->m_display)
271  {
272  XResetScreenSaver(d->m_display->GetDisplay());
273  d->m_display->Sync();
274  }
275 
276  if (d->IsScreenSaverRunning())
277  d->StopTimer();
278 }
279 
281 {
282  bool need_xsync = false;
283  Display *dsp = nullptr;
284  if (d->m_display)
285  dsp = d->m_display->GetDisplay();
286 
287  if (dsp)
288  {
289  XResetScreenSaver(dsp);
290  need_xsync = true;
291  }
292 
293  if (d->IsScreenSaverRunning())
294  resetSlot();
295 
296  if (Asleep() && dsp)
297  {
298  DPMSForceLevel(dsp, DPMSModeOn);
299  need_xsync = true;
300  }
301 
302  if (need_xsync && d->m_display)
303  d->m_display->Sync();
304 }
305 
307 {
308  if (!d->IsDPMSEnabled())
309  return false;
310 
311  if (d->DeactivatedDPMS())
312  return false;
313 
314  BOOL on = false;
315  CARD16 power_level = DPMSModeOn;
316 
317  if (d->m_display)
318  DPMSInfo(d->m_display->GetDisplay(), &power_level, &on);
319 
320  return (power_level != DPMSModeOn);
321 }
322 
324 {
325  d->ResetScreenSaver();
326 }
Display * GetDisplay(void)
Definition: mythxdisplay.h:28
int GetNumSettingOnHost(const QString &key, const QString &host, int defaultval)
Definition: mythdb.cpp:686
bool Asleep(void) override
class ScreenSaverX11Private * d
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
ScreenSaverX11Private(ScreenSaverX11 *outer)
#define LOC
ScreenSaverState m_state
bool IsDPMSEnabled(void) const
void Sync(bool Flush=false)
static const uint16_t * d
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
unsigned int uint
Definition: compat.h:140
bool m_dpmsdeactivated
true if we disabled DPMS
uint myth_system(const QString &command, uint flags, uint timeout)
void Disable(void) override
process events while waiting
Definition: mythsystem.h:37
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
avoid disabling UI drawing
Definition: mythsystem.h:35
run child in the background
Definition: mythsystem.h:36
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
~ScreenSaverX11() override
void Restore(void) override
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:34
bool DeactivatedDPMS(void) const
void Reset(void) override
bool IsScreenSaverRunning(void) const