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, dummy1 = 0;
53  m_dpmsaware = DPMSQueryExtension(m_display->GetDisplay(),
54  &dummy0, &dummy1);
55  }
56  else
57  {
58  LOG(VB_GENERAL, LOG_ERR, LOC +
59  "Failed to open connection to X11 server");
60  }
61 
62  if (m_dpmsaware)
63  {
64  CARD16 power_level = 0;
65 
66  /* If someone runs into X server weirdness that goes away when
67  * they externally disable DPMS, then the 'dpmsenabled' test should
68  * be short circuited by a call to 'DPMSCapable()'. Be sure to
69  * manually initialize dpmsenabled to false.
70  */
71 
72  DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
73 
74  if (m_dpmsenabled)
75  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
76  else
77  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
78  }
79  else
80  {
81  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
82  }
83  }
84 
86  {
87  // m_resetTimer deleted by ScreenSaverX11 QObject dtor
88  delete m_display;
89  }
90 
91  bool IsScreenSaverRunning(void) const
92  {
93  return m_xscreensaverRunning;
94  }
95 
96  bool IsDPMSEnabled(void) const { return m_dpmsenabled; }
97 
98  void StopTimer(void)
99  {
100  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
101  if (m_resetTimer)
102  m_resetTimer->stop();
103  }
104 
105  void StartTimer(void)
106  {
107  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
108  if (m_resetTimer)
110  }
111 
112  void ResetTimer(void)
113  {
114  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
115 
116  StopTimer();
117 
118  if (m_timeoutInterval == -1)
119  {
121  "xscreensaverInterval", GetMythDB()->GetHostName(), 50) * 1000;
122  }
123 
124  if (m_timeoutInterval > 0)
125  StartTimer();
126 
127  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
128  }
129 
130  // DPMS
131  bool DeactivatedDPMS(void) const
132  {
133  return m_dpmsdeactivated;
134  }
135 
136  void DisableDPMS(void)
137  {
138  if (IsDPMSEnabled() && m_display)
139  {
140  m_dpmsdeactivated = true;
141  Status status = DPMSDisable(m_display->GetDisplay());
142  m_display->Sync();
143  LOG(VB_GENERAL, LOG_INFO, LOC +
144  QString("DPMS Deactivated %1").arg(status));
145  }
146  }
147 
148  void RestoreDPMS(void)
149  {
151  {
152  m_dpmsdeactivated = false;
153  Status status = DPMSEnable(m_display->GetDisplay());
154  m_display->Sync();
155  LOG(VB_GENERAL, LOG_INFO, LOC +
156  QString("DPMS Reactivated %1").arg(status));
157  }
158  }
159 
160  void SaveScreenSaver(void)
161  {
162  if (!m_state.saved && m_display)
163  {
164  XGetScreenSaver(m_display->GetDisplay(), &m_state.timeout,
167  m_state.saved = true;
168  }
169  }
170 
172  {
173  if (m_state.saved && m_display)
174  {
175  XSetScreenSaver(m_display->GetDisplay(), m_state.timeout,
178  m_display->Sync();
179  m_state.saved = false;
180  }
181  }
182 
183  void ResetScreenSaver(void)
184  {
185  if (!IsScreenSaverRunning())
186  return;
187 
188  QDateTime current_time = MythDate::current();
189  if ((!m_last_deactivated.isValid()) ||
190  (m_last_deactivated.secsTo(current_time) > 30))
191  {
193  {
194  LOG(VB_PLAYBACK, LOG_INFO, LOC +
195  "Calling xscreensaver-command -deactivate");
196  myth_system("xscreensaver-command -deactivate >&- 2>&- &",
200  }
201  m_last_deactivated = current_time;
202  }
203  }
204 
205  private:
207  {
208  public:
209  ScreenSaverState() = default;
210  bool saved {false};
211  int timeout {-1};
212  int interval {-1};
213  int preferblank {-1};
214  int allowexposure {-1};
215  };
216 
217  private:
218  bool m_dpmsaware {false};
219  bool m_dpmsdeactivated {false};
220  bool m_xscreensaverRunning {false};
221  BOOL m_dpmsenabled {false};
222 
224  QTimer *m_resetTimer {nullptr};
225 
227 
230 };
231 
233  d(new ScreenSaverX11Private(this))
234 {
235 }
236 
238 {
239  /* Ensure DPMS gets left as it was found. */
240  if (d->DeactivatedDPMS())
242 
243  delete d;
244 }
245 
247 {
248  d->SaveScreenSaver();
249 
250  if (d->m_display)
251  {
252  XResetScreenSaver(d->m_display->GetDisplay());
253  XSetScreenSaver(d->m_display->GetDisplay(), 0, 0, 0, 0);
254  d->m_display->Sync();
255  }
256 
257  d->DisableDPMS();
258 
259  if (d->IsScreenSaverRunning())
260  d->ResetTimer();
261 }
262 
264 {
266  d->RestoreDPMS();
267 
268  // One must reset after the restore
269  if (d->m_display)
270  {
271  XResetScreenSaver(d->m_display->GetDisplay());
272  d->m_display->Sync();
273  }
274 
275  if (d->IsScreenSaverRunning())
276  d->StopTimer();
277 }
278 
280 {
281  bool need_xsync = false;
282  Display *dsp = nullptr;
283  if (d->m_display)
284  dsp = d->m_display->GetDisplay();
285 
286  if (dsp)
287  {
288  XResetScreenSaver(dsp);
289  need_xsync = true;
290  }
291 
292  if (d->IsScreenSaverRunning())
293  resetSlot();
294 
295  if (Asleep() && dsp)
296  {
297  DPMSForceLevel(dsp, DPMSModeOn);
298  need_xsync = true;
299  }
300 
301  if (need_xsync && d->m_display)
302  d->m_display->Sync();
303 }
304 
306 {
307  if (!d->IsDPMSEnabled())
308  return false;
309 
310  if (d->DeactivatedDPMS())
311  return false;
312 
313  BOOL on = false;
314  CARD16 power_level = DPMSModeOn;
315 
316  if (d->m_display)
317  DPMSInfo(d->m_display->GetDisplay(), &power_level, &on);
318 
319  return (power_level != DPMSModeOn);
320 }
321 
323 {
324  d->ResetScreenSaver();
325 }
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
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