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:
35  m_timeoutInterval(-1), m_resetTimer(nullptr),
36  m_display(nullptr)
37  {
41  myth_system("xscreensaver-command -version >&- 2>&-",
42  flags) == 0;
43 
45  {
46  m_resetTimer = new QTimer(outer);
47  m_resetTimer->setSingleShot(false);
48  QObject::connect(m_resetTimer, SIGNAL(timeout()),
49  outer, SLOT(resetSlot()));
51  LOG(VB_GENERAL, LOG_INFO, LOC + "XScreenSaver support enabled");
52  }
53 
55  if (m_display)
56  {
57  int dummy0, dummy1;
58  m_dpmsaware = DPMSQueryExtension(m_display->GetDisplay(),
59  &dummy0, &dummy1);
60  }
61  else
62  {
63  LOG(VB_GENERAL, LOG_ERR, LOC +
64  "Failed to open connection to X11 server");
65  }
66 
67  if (m_dpmsaware)
68  {
69  CARD16 power_level;
70 
71  /* If someone runs into X server weirdness that goes away when
72  * they externally disable DPMS, then the 'dpmsenabled' test should
73  * be short circuited by a call to 'DPMSCapable()'. Be sure to
74  * manually initialize dpmsenabled to false.
75  */
76 
77  DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
78 
79  if (m_dpmsenabled)
80  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
81  else
82  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
83  }
84  else
85  {
86  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
87  }
88  }
89 
91  {
92  // m_resetTimer deleted by ScreenSaverX11 QObject dtor
93  delete m_display;
94  }
95 
96  bool IsScreenSaverRunning(void) const
97  {
98  return m_xscreensaverRunning;
99  }
100 
101  bool IsDPMSEnabled(void) const { return m_dpmsenabled; }
102 
103  void StopTimer(void)
104  {
105  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
106  if (m_resetTimer)
107  m_resetTimer->stop();
108  }
109 
110  void StartTimer(void)
111  {
112  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
113  if (m_resetTimer)
115  }
116 
117  void ResetTimer(void)
118  {
119  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
120 
121  StopTimer();
122 
123  if (m_timeoutInterval == -1)
124  {
126  "xscreensaverInterval", GetMythDB()->GetHostName(), 50) * 1000;
127  }
128 
129  if (m_timeoutInterval > 0)
130  StartTimer();
131 
132  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
133  }
134 
135  // DPMS
136  bool DeactivatedDPMS(void) const
137  {
138  return m_dpmsdeactivated;
139  }
140 
141  void DisableDPMS(void)
142  {
143  if (IsDPMSEnabled() && m_display)
144  {
145  m_dpmsdeactivated = true;
146  Status status = DPMSDisable(m_display->GetDisplay());
147  m_display->Sync();
148  LOG(VB_GENERAL, LOG_INFO, LOC +
149  QString("DPMS Deactivated %1").arg(status));
150  }
151  }
152 
153  void RestoreDPMS(void)
154  {
156  {
157  m_dpmsdeactivated = false;
158  Status status = DPMSEnable(m_display->GetDisplay());
159  m_display->Sync();
160  LOG(VB_GENERAL, LOG_INFO, LOC +
161  QString("DPMS Reactivated %1").arg(status));
162  }
163  }
164 
165  void SaveScreenSaver(void)
166  {
167  if (!m_state.saved && m_display)
168  {
169  XGetScreenSaver(m_display->GetDisplay(), &m_state.timeout,
172  m_state.saved = true;
173  }
174  }
175 
177  {
178  if (m_state.saved && m_display)
179  {
180  XSetScreenSaver(m_display->GetDisplay(), m_state.timeout,
183  m_display->Sync();
184  m_state.saved = false;
185  }
186  }
187 
188  void ResetScreenSaver(void)
189  {
190  if (!IsScreenSaverRunning())
191  return;
192 
193  QDateTime current_time = MythDate::current();
194  if ((!m_last_deactivated.isValid()) ||
195  (m_last_deactivated.secsTo(current_time) > 30))
196  {
198  {
199  LOG(VB_PLAYBACK, LOG_INFO, LOC +
200  "Calling xscreensaver-command -deactivate");
201  myth_system("xscreensaver-command -deactivate >&- 2>&- &",
205  }
206  m_last_deactivated = current_time;
207  }
208  }
209 
210  private:
212  {
213  public:
214  ScreenSaverState() = default;
215  bool saved {false};
216  int timeout {-1};
217  int interval {-1};
218  int preferblank {-1};
219  int allowexposure {-1};
220  };
221 
222  private:
227 
229  QTimer *m_resetTimer;
230 
232 
235 };
236 
238  d(new ScreenSaverX11Private(this))
239 {
240 }
241 
243 {
244  /* Ensure DPMS gets left as it was found. */
245  if (d->DeactivatedDPMS())
246  Restore();
247 
248  delete d;
249 }
250 
252 {
253  d->SaveScreenSaver();
254 
255  if (d->m_display)
256  {
257  XResetScreenSaver(d->m_display->GetDisplay());
258  XSetScreenSaver(d->m_display->GetDisplay(), 0, 0, 0, 0);
259  d->m_display->Sync();
260  }
261 
262  d->DisableDPMS();
263 
264  if (d->IsScreenSaverRunning())
265  d->ResetTimer();
266 }
267 
269 {
271  d->RestoreDPMS();
272 
273  // One must reset after the restore
274  if (d->m_display)
275  {
276  XResetScreenSaver(d->m_display->GetDisplay());
277  d->m_display->Sync();
278  }
279 
280  if (d->IsScreenSaverRunning())
281  d->StopTimer();
282 }
283 
285 {
286  bool need_xsync = false;
287  Display *dsp = nullptr;
288  if (d->m_display)
289  dsp = d->m_display->GetDisplay();
290 
291  if (dsp)
292  {
293  XResetScreenSaver(dsp);
294  need_xsync = true;
295  }
296 
297  if (d->IsScreenSaverRunning())
298  resetSlot();
299 
300  if (Asleep() && dsp)
301  {
302  DPMSForceLevel(dsp, DPMSModeOn);
303  need_xsync = true;
304  }
305 
306  if (need_xsync && d->m_display)
307  d->m_display->Sync();
308 }
309 
311 {
312  if (!d->IsDPMSEnabled())
313  return false;
314 
315  if (d->DeactivatedDPMS())
316  return false;
317 
318  BOOL on;
319  CARD16 power_level = DPMSModeOn;
320 
321  if (d->m_display)
322  DPMSInfo(d->m_display->GetDisplay(), &power_level, &on);
323 
324  return (power_level != DPMSModeOn);
325 }
326 
328 {
329  d->ResetScreenSaver();
330 }
MythXDisplay * OpenMythXDisplay(void)
Display * GetDisplay(void)
Definition: mythxdisplay.h:21
avoid disabling UI drawing
Definition: mythsystem.h:35
int GetNumSettingOnHost(const QString &key, const QString &host, int defaultval)
Definition: mythdb.cpp:675
run child in the background
Definition: mythsystem.h:36
bool Asleep(void) override
class ScreenSaverX11Private * d
This file is intended to hold X11 specific utility functions.
Definition: mythxdisplay.h:16
unsigned int uint
Definition: compat.h:140
ScreenSaverX11Private(ScreenSaverX11 *outer)
#define LOC
void Sync(bool flush=false)
process events while waiting
Definition: mythsystem.h:37
ScreenSaverState m_state
bool IsDPMSEnabled(void) const
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
static const uint16_t * d
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
bool m_dpmsdeactivated
true if we disabled DPMS
uint myth_system(const QString &command, uint flags, uint timeout)
void Disable(void) override
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
void Restore(void) override
bool DeactivatedDPMS(void) const
void Reset(void) override
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:34
bool IsScreenSaverRunning(void) const