MythTV  master
mythscreensaverx11.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QDateTime>
3 #include <QTimer>
4 
5 // MythTV
6 #include "mythlogging.h"
7 #include "mythcorecontext.h"
8 #include "mythdate.h"
9 #include "mythsystemlegacy.h"
10 #include "platforms/mythxdisplay.h"
12 
13 // X11 headers
14 #include <X11/Xlib.h>
15 extern "C" {
16 #include <X11/extensions/dpms.h>
17 }
18 
19 #define LOC QString("ScreenSaverX11: ")
20 
22 {
23  friend class MythScreenSaverX11;
24 
25  public:
27  {
30  m_xscreensaverRunning = myth_system("xscreensaver-command -version >&- 2>&-", flags) == 0;
32  {
33  m_resetTimer = new QTimer(outer);
34  m_resetTimer->setSingleShot(false);
35  QObject::connect(m_resetTimer, &QTimer::timeout, outer, &MythScreenSaverX11::ResetSlot);
37  LOG(VB_GENERAL, LOG_INFO, LOC + "XScreenSaver support enabled");
38  }
39 
41  if (m_display)
42  {
43  int dummy0 = 0;
44  int dummy1 = 0;
45  m_dpmsaware = (DPMSQueryExtension(m_display->GetDisplay(), &dummy0, &dummy1) != 0);
46  }
47  else
48  {
49  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open connection to X11 server");
50  }
51 
52  if (m_dpmsaware && m_display)
53  {
54  CARD16 power_level = 0;
55 
56  /* If someone runs into X server weirdness that goes away when
57  * they externally disable DPMS, then the 'dpmsenabled' test should
58  * be short circuited by a call to 'DPMSCapable()'. Be sure to
59  * manually initialize dpmsenabled to false.
60  */
61 
62  DPMSInfo(m_display->GetDisplay(), &power_level, &m_dpmsenabled);
63 
64  if (static_cast<bool>(m_dpmsenabled))
65  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is active.");
66  else
67  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is disabled.");
68  }
69  else
70  {
71  LOG(VB_GENERAL, LOG_INFO, LOC + "DPMS is not supported.");
72  }
73  }
74 
76  {
77  // m_resetTimer deleted by ScreenSaverX11 QObject dtor
78  delete m_display;
79  }
80 
81  bool IsScreenSaverRunning() const
82  {
83  return m_xscreensaverRunning;
84  }
85 
86  bool IsDPMSEnabled() const { return static_cast<bool>(m_dpmsenabled); }
87 
88  void StopTimer()
89  {
90  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StopTimer");
91  if (m_resetTimer)
92  m_resetTimer->stop();
93  }
94 
95  void StartTimer()
96  {
97  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "StartTimer");
98  if (m_resetTimer)
100  }
101 
102  void ResetTimer()
103  {
104  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- begin");
105  StopTimer();
106  // To be clear - this setting has no UI
107  if (m_timeoutInterval == -1)
108  m_timeoutInterval = gCoreContext->GetNumSetting("xscreensaverInterval", 50) * 1000;
109  if (m_timeoutInterval > 0)
110  StartTimer();
111  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "ResetTimer -- end");
112  }
113 
114  // DPMS
115  bool DeactivatedDPMS() const
116  {
117  return m_dpmsdeactivated;
118  }
119 
120  void DisableDPMS()
121  {
122  if (IsDPMSEnabled() && m_display)
123  {
124  m_dpmsdeactivated = true;
125  Status status = DPMSDisable(m_display->GetDisplay());
126  m_display->Sync();
127  LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Deactivated %1").arg(status));
128  }
129  }
130 
131  void RestoreDPMS()
132  {
134  {
135  m_dpmsdeactivated = false;
136  Status status = DPMSEnable(m_display->GetDisplay());
137  m_display->Sync();
138  LOG(VB_GENERAL, LOG_INFO, LOC + QString("DPMS Reactivated %1").arg(status));
139  }
140  }
141 
143  {
144  if (!m_state.m_saved && m_display)
145  {
146  XGetScreenSaver(m_display->GetDisplay(), &m_state.m_timeout,
149  m_state.m_saved = true;
150  }
151  }
152 
154  {
155  if (m_state.m_saved && m_display)
156  {
157  if (XSetScreenSaver(m_display->GetDisplay(), m_state.m_timeout,
159  m_state.m_allowexposure) == 1)
160  {
161  LOG(VB_GENERAL, LOG_INFO, LOC + "Uninhibited screensaver");
162  }
163  else
164  {
165  LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to re-enable screensaver");
166  }
167  m_display->Sync();
168  m_state.m_saved = false;
169  }
170  }
171 
173  {
174  if (!IsScreenSaverRunning())
175  return;
176 
177  QDateTime current_time = MythDate::current();
178  if ((!m_lastDeactivated.isValid()) ||
179  (m_lastDeactivated.secsTo(current_time) > 30))
180  {
182  {
183  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling xscreensaver-command -deactivate");
184  myth_system("xscreensaver-command -deactivate >&- 2>&- &",
186  }
187  m_lastDeactivated = current_time;
188  }
189  }
190 
191  private:
193  {
194  public:
195  ScreenSaverState() = default;
196  bool m_saved {false};
197  int m_timeout {-1};
198  int m_interval {-1};
199  int m_preferblank {-1};
200  int m_allowexposure {-1};
201  };
202 
203  private:
204  bool m_dpmsaware {false};
205  bool m_dpmsdeactivated {false};
206  bool m_xscreensaverRunning {false};
207  BOOL m_dpmsenabled {static_cast<BOOL>(false)};
208 
210  QTimer *m_resetTimer {nullptr};
211 
212  QDateTime m_lastDeactivated;
213 
216 };
217 
219  : MythScreenSaver(Parent),
220  m_priv(new ScreenSaverX11Private(this))
221 {
222 }
223 
225 {
226  // Ensure DPMS gets left as it was found.
227  if (m_priv->DeactivatedDPMS())
229 
230  delete m_priv;
231 }
232 
234 {
236 
237  if (m_priv->m_display)
238  {
239  int reset = XResetScreenSaver(m_priv->m_display->GetDisplay());
240  int set = XSetScreenSaver(m_priv->m_display->GetDisplay(), 0, 0, 0, 0);
241  if (reset != 1)
242  LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to reset screensaver");
243  if (set != 1)
244  LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to disable screensaver");
245  if (reset && set)
246  LOG(VB_GENERAL, LOG_INFO, LOC + "Inhibited X11 screensaver");
247  m_priv->m_display->Sync();
248  }
249 
250  m_priv->DisableDPMS();
251 
253  m_priv->ResetTimer();
254 }
255 
257 {
259  m_priv->RestoreDPMS();
260 
261  // One must reset after the restore
262  if (m_priv->m_display)
263  {
264  XResetScreenSaver(m_priv->m_display->GetDisplay());
265  m_priv->m_display->Sync();
266  }
267 
269  m_priv->StopTimer();
270 }
271 
273 {
274  bool need_xsync = false;
275  Display *dsp = nullptr;
276  if (m_priv->m_display)
277  dsp = m_priv->m_display->GetDisplay();
278 
279  if (dsp)
280  {
281  XResetScreenSaver(dsp);
282  need_xsync = true;
283  }
284 
286  ResetSlot();
287 
288  if (Asleep() && dsp)
289  {
290  DPMSForceLevel(dsp, DPMSModeOn);
291  need_xsync = true;
292  }
293 
294  if (need_xsync && m_priv->m_display)
295  m_priv->m_display->Sync();
296 }
297 
299 {
300  if (!m_priv->IsDPMSEnabled())
301  return false;
302 
303  if (m_priv->DeactivatedDPMS())
304  return false;
305 
306  BOOL on = static_cast<BOOL>(false);
307  CARD16 power_level = DPMSModeOn;
308 
309  if (m_priv->m_display)
310  DPMSInfo(m_priv->m_display->GetDisplay(), &power_level, &on);
311 
312  return (power_level != DPMSModeOn);
313 }
314 
316 {
318 }
ScreenSaverX11Private::ScreenSaverState::m_interval
int m_interval
Definition: mythscreensaverx11.cpp:198
MythScreenSaverX11
Definition: mythscreensaverx11.h:11
ScreenSaverX11Private::m_xscreensaverRunning
bool m_xscreensaverRunning
Definition: mythscreensaverx11.cpp:206
myth_system
uint myth_system(const QString &command, uint flags, uint timeout)
Definition: mythsystemlegacy.cpp:501
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
ScreenSaverX11Private::RestoreScreenSaver
void RestoreScreenSaver()
Definition: mythscreensaverx11.cpp:153
kMSDontBlockInputDevs
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:34
ScreenSaverX11Private::ResetScreenSaver
void ResetScreenSaver()
Definition: mythscreensaverx11.cpp:172
ScreenSaverX11Private::StartTimer
void StartTimer()
Definition: mythscreensaverx11.cpp:95
ScreenSaverX11Private::~ScreenSaverX11Private
~ScreenSaverX11Private()
Definition: mythscreensaverx11.cpp:75
ScreenSaverX11Private::ResetTimer
void ResetTimer()
Definition: mythscreensaverx11.cpp:102
ScreenSaverX11Private::m_dpmsaware
bool m_dpmsaware
Definition: mythscreensaverx11.cpp:204
mythscreensaverx11.h
ScreenSaverX11Private::StopTimer
void StopTimer()
Definition: mythscreensaverx11.cpp:88
arg
arg(title).arg(filename).arg(doDelete))
ScreenSaverX11Private::m_dpmsenabled
BOOL m_dpmsenabled
Definition: mythscreensaverx11.cpp:207
ScreenSaverX11Private::IsScreenSaverRunning
bool IsScreenSaverRunning() const
Definition: mythscreensaverx11.cpp:81
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenSaver
Base Class for screensavers.
Definition: mythscreensaver.h:15
ScreenSaverX11Private::DisableDPMS
void DisableDPMS()
Definition: mythscreensaverx11.cpp:120
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:10
MythXDisplay::OpenMythXDisplay
static MythXDisplay * OpenMythXDisplay(bool Warn=true)
Definition: mythxdisplay.cpp:44
mythsystemlegacy.h
ScreenSaverX11Private::ScreenSaverState::m_preferblank
int m_preferblank
Definition: mythscreensaverx11.cpp:199
mythdate.h
ScreenSaverX11Private::m_lastDeactivated
QDateTime m_lastDeactivated
Definition: mythscreensaverx11.cpp:212
mythlogging.h
ScreenSaverX11Private::ScreenSaverState::m_timeout
int m_timeout
Definition: mythscreensaverx11.cpp:197
ScreenSaverX11Private::RestoreDPMS
void RestoreDPMS()
Definition: mythscreensaverx11.cpp:131
ScreenSaverX11Private::m_dpmsdeactivated
bool m_dpmsdeactivated
true if we disabled DPMS
Definition: mythscreensaverx11.cpp:205
ScreenSaverX11Private::IsDPMSEnabled
bool IsDPMSEnabled() const
Definition: mythscreensaverx11.cpp:86
ScreenSaverX11Private::ScreenSaverState::m_allowexposure
int m_allowexposure
Definition: mythscreensaverx11.cpp:200
MythScreenSaverX11::Restore
void Restore() override
Definition: mythscreensaverx11.cpp:256
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:933
MythXDisplay::GetDisplay
Display * GetDisplay(void)
Definition: mythxdisplay.h:31
ScreenSaverX11Private::DeactivatedDPMS
bool DeactivatedDPMS() const
Definition: mythscreensaverx11.cpp:115
MythScreenSaverX11::MythScreenSaverX11
MythScreenSaverX11(QObject *Parent)
Definition: mythscreensaverx11.cpp:218
kMSRunBackground
@ kMSRunBackground
run child in the background
Definition: mythsystem.h:36
mythxdisplay.h
ScreenSaverX11Private::ScreenSaverState::ScreenSaverState
ScreenSaverState()=default
MythScreenSaverX11::Reset
void Reset() override
Definition: mythscreensaverx11.cpp:272
MythScreenSaverX11::Disable
void Disable() override
Definition: mythscreensaverx11.cpp:233
MythXDisplay::Sync
void Sync(bool Flush=false)
Definition: mythxdisplay.cpp:147
ScreenSaverX11Private::ScreenSaverX11Private
ScreenSaverX11Private(MythScreenSaverX11 *outer)
Definition: mythscreensaverx11.cpp:26
mythcorecontext.h
LOC
#define LOC
Definition: mythscreensaverx11.cpp:19
ScreenSaverX11Private::SaveScreenSaver
void SaveScreenSaver()
Definition: mythscreensaverx11.cpp:142
kMSProcessEvents
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:37
MythScreenSaverX11::ResetSlot
void ResetSlot()
Definition: mythscreensaverx11.cpp:315
MythScreenSaverX11::~MythScreenSaverX11
~MythScreenSaverX11() override
Definition: mythscreensaverx11.cpp:224
MythXDisplay
Definition: mythxdisplay.h:22
ScreenSaverX11Private::ScreenSaverState::m_saved
bool m_saved
Definition: mythscreensaverx11.cpp:196
ScreenSaverX11Private
Definition: mythscreensaverx11.cpp:22
MythScreenSaverX11::Asleep
bool Asleep() override
Definition: mythscreensaverx11.cpp:298
ScreenSaverX11Private::m_resetTimer
QTimer * m_resetTimer
Definition: mythscreensaverx11.cpp:210
kMSDontDisableDrawing
@ kMSDontDisableDrawing
avoid disabling UI drawing
Definition: mythsystem.h:35
ScreenSaverX11Private::m_state
ScreenSaverState m_state
Definition: mythscreensaverx11.cpp:214
ScreenSaverX11Private::ScreenSaverState
Definition: mythscreensaverx11.cpp:193
ScreenSaverX11Private::m_display
MythXDisplay * m_display
Definition: mythscreensaverx11.cpp:215
ScreenSaverX11Private::m_timeoutInterval
int m_timeoutInterval
Definition: mythscreensaverx11.cpp:209