MythTV  master
mythscreensaverx11.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QDateTime>
3 #include <QTimer>
4 
5 // MythTV
7 #include "libmythbase/mythdate.h"
10 
11 #include "platforms/mythxdisplay.h"
13 
14 // X11 headers
15 #include <X11/Xlib.h>
16 extern "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);
36  QObject::connect(m_resetTimer, &QTimer::timeout, Parent, &MythScreenSaverX11::ResetSlot);
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 
53  if (m_dpmsaware && m_display)
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 
82  bool IsScreenSaverRunning() const
83  {
84  return m_xscreensaverRunning;
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 
96  void StartTimer()
97  {
98  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
99  if (m_resetTimer)
101  }
102 
103  void ResetTimer()
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 
121  void DisableDPMS()
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 
132  void RestoreDPMS()
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  {
156  if (m_state.m_saved && m_display)
157  {
158  if (XSetScreenSaver(m_display->GetDisplay(), m_state.m_timeout,
160  m_state.m_allowexposure) == 1)
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  {
175  if (!IsScreenSaverRunning())
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};
200  int m_preferblank {-1};
201  int m_allowexposure {-1};
202  };
203 
204  private:
205  Q_DISABLE_COPY(ScreenSaverX11Private)
206  bool m_dpmsaware {false};
207  bool m_dpmsdeactivated {false};
208  bool m_xscreensaverRunning {false};
209  BOOL m_dpmsenabled {static_cast<BOOL>(false)};
210 
211  std::chrono::seconds m_timeoutInterval {-1s};
212  QTimer *m_resetTimer {nullptr};
213 
214  QDateTime m_lastDeactivated;
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");
249  m_priv->m_display->Sync();
250  }
251 
252  m_priv->DisableDPMS();
253 
255  m_priv->ResetTimer();
256 }
257 
259 {
261  m_priv->RestoreDPMS();
262 
263  // One must reset after the restore
264  if (m_priv->m_display)
265  {
266  XResetScreenSaver(m_priv->m_display->GetDisplay());
267  m_priv->m_display->Sync();
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)
297  m_priv->m_display->Sync();
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 }
ScreenSaverX11Private::ScreenSaverState::m_interval
int m_interval
Definition: mythscreensaverx11.cpp:199
MythScreenSaverX11
Definition: mythscreensaverx11.h:10
ScreenSaverX11Private::m_xscreensaverRunning
bool m_xscreensaverRunning
Definition: mythscreensaverx11.cpp:208
bool
bool
Definition: pxsup2dast.c:30
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
ScreenSaverX11Private::RestoreScreenSaver
void RestoreScreenSaver()
Definition: mythscreensaverx11.cpp:154
kMSDontBlockInputDevs
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
MythXDisplay::GetDisplay
Display * GetDisplay()
Definition: mythxdisplay.h:25
ScreenSaverX11Private::ResetScreenSaver
void ResetScreenSaver()
Definition: mythscreensaverx11.cpp:173
ScreenSaverX11Private::StartTimer
void StartTimer()
Definition: mythscreensaverx11.cpp:96
ScreenSaverX11Private::~ScreenSaverX11Private
~ScreenSaverX11Private()
Definition: mythscreensaverx11.cpp:76
ScreenSaverX11Private::ScreenSaverX11Private
ScreenSaverX11Private(MythScreenSaverX11 *Parent)
Definition: mythscreensaverx11.cpp:27
ScreenSaverX11Private::ResetTimer
void ResetTimer()
Definition: mythscreensaverx11.cpp:103
ScreenSaverX11Private::m_dpmsaware
bool m_dpmsaware
Definition: mythscreensaverx11.cpp:206
mythscreensaverx11.h
ScreenSaverX11Private::m_timeoutInterval
std::chrono::seconds m_timeoutInterval
Definition: mythscreensaverx11.cpp:211
ScreenSaverX11Private::StopTimer
void StopTimer()
Definition: mythscreensaverx11.cpp:89
ScreenSaverX11Private::m_dpmsenabled
BOOL m_dpmsenabled
Definition: mythscreensaverx11.cpp:209
ScreenSaverX11Private::IsScreenSaverRunning
bool IsScreenSaverRunning() const
Definition: mythscreensaverx11.cpp:82
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythScreenSaver
Base Class for screensavers.
Definition: mythscreensaver.h:14
ScreenSaverX11Private::DisableDPMS
void DisableDPMS()
Definition: mythscreensaverx11.cpp:121
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
MythScreenSaverX11::m_priv
class ScreenSaverX11Private * m_priv
Definition: mythscreensaverx11.h:26
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
MythXDisplay::OpenMythXDisplay
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
Definition: mythxdisplay.cpp:25
mythsystemlegacy.h
ScreenSaverX11Private::ScreenSaverState::m_preferblank
int m_preferblank
Definition: mythscreensaverx11.cpp:200
mythdate.h
ScreenSaverX11Private::m_lastDeactivated
QDateTime m_lastDeactivated
Definition: mythscreensaverx11.cpp:214
mythlogging.h
ScreenSaverX11Private::ScreenSaverState::m_timeout
int m_timeout
Definition: mythscreensaverx11.cpp:198
ScreenSaverX11Private::RestoreDPMS
void RestoreDPMS()
Definition: mythscreensaverx11.cpp:132
MythCoreContext::GetDurSetting
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
Definition: mythcorecontext.h:168
ScreenSaverX11Private::m_dpmsdeactivated
bool m_dpmsdeactivated
true if we disabled DPMS
Definition: mythscreensaverx11.cpp:207
ScreenSaverX11Private::IsDPMSEnabled
bool IsDPMSEnabled() const
Definition: mythscreensaverx11.cpp:87
ScreenSaverX11Private::ScreenSaverState::m_allowexposure
int m_allowexposure
Definition: mythscreensaverx11.cpp:201
MythScreenSaverX11::Restore
void Restore() override
Definition: mythscreensaverx11.cpp:258
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ScreenSaverX11Private::DeactivatedDPMS
bool DeactivatedDPMS() const
Definition: mythscreensaverx11.cpp:116
MythScreenSaverX11::MythScreenSaverX11
MythScreenSaverX11(QObject *Parent)
Definition: mythscreensaverx11.cpp:220
kMSRunBackground
@ kMSRunBackground
run child in the background
Definition: mythsystem.h:38
mythxdisplay.h
ScreenSaverX11Private::ScreenSaverState::ScreenSaverState
ScreenSaverState()=default
MythScreenSaverX11::Reset
void Reset() override
Definition: mythscreensaverx11.cpp:274
MythScreenSaverX11::Disable
void Disable() override
Definition: mythscreensaverx11.cpp:235
MythXDisplay::Sync
void Sync(bool Flush=false)
Definition: mythxdisplay.cpp:120
mythcorecontext.h
LOC
#define LOC
Definition: mythscreensaverx11.cpp:20
ScreenSaverX11Private::SaveScreenSaver
void SaveScreenSaver()
Definition: mythscreensaverx11.cpp:143
kMSProcessEvents
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
MythScreenSaverX11::ResetSlot
void ResetSlot()
Definition: mythscreensaverx11.cpp:317
MythScreenSaverX11::~MythScreenSaverX11
~MythScreenSaverX11() override
Definition: mythscreensaverx11.cpp:226
MythXDisplay
Definition: mythxdisplay.h:15
ScreenSaverX11Private::ScreenSaverState::m_saved
bool m_saved
Definition: mythscreensaverx11.cpp:197
ScreenSaverX11Private
Definition: mythscreensaverx11.cpp:22
MythScreenSaverX11::Asleep
bool Asleep() override
Definition: mythscreensaverx11.cpp:300
ScreenSaverX11Private::m_resetTimer
QTimer * m_resetTimer
Definition: mythscreensaverx11.cpp:212
kMSDontDisableDrawing
@ kMSDontDisableDrawing
avoid disabling UI drawing
Definition: mythsystem.h:37
ScreenSaverX11Private::m_state
ScreenSaverState m_state
Definition: mythscreensaverx11.cpp:216
ScreenSaverX11Private::ScreenSaverState
Definition: mythscreensaverx11.cpp:193
ScreenSaverX11Private::m_display
MythXDisplay * m_display
Definition: mythscreensaverx11.cpp:217