00001 #define QT_CLEAN_NAMESPACE // no qt 1.x compatability, INT32 conflicts with X
00002 #include "screensaver-x11.h"
00003 #include <qdatetime.h>
00004 #include <qtimer.h>
00005
00006 #include <X11/Xlib.h>
00007
00008 extern "C" {
00009 #include <X11/extensions/dpms.h>
00010 }
00011
00012 #include "mythcontext.h"
00013 #include "util.h"
00014
00015 class ScreenSaverX11Private
00016 {
00017 friend class ScreenSaverX11;
00018
00019 public:
00020 ScreenSaverX11Private(ScreenSaverX11 *outer) : m_dpmsenabled(FALSE),
00021 m_dpmsdeactivated(false), m_timeoutInterval(-1), m_resetTimer(0)
00022 {
00023 m_xscreensaverRunning =
00024 myth_system("xscreensaver-command -version >&- 2>&-") == 0;
00025 m_gscreensaverRunning =
00026 myth_system("gnome-screensaver-command --help >&- 2>&-") == 0;
00027
00028 if (IsScreenSaverRunning())
00029 {
00030 m_resetTimer = new QTimer(outer);
00031 QObject::connect(m_resetTimer, SIGNAL(timeout()),
00032 outer, SLOT(resetSlot()));
00033 VERBOSE(VB_GENERAL, "XScreenSaver support enabled");
00034 }
00035
00036 int dummy;
00037 if ((m_dpmsaware = DPMSQueryExtension(qt_xdisplay(), &dummy, &dummy)))
00038 {
00039 CARD16 power_level;
00040
00041
00042
00043
00044
00045
00046
00047 DPMSInfo(qt_xdisplay(), &power_level, &m_dpmsenabled);
00048
00049 if (m_dpmsenabled)
00050 VERBOSE(VB_GENERAL, "DPMS is active.");
00051 else
00052 VERBOSE(VB_GENERAL, "DPMS is disabled.");
00053 }
00054 else
00055 {
00056 VERBOSE(VB_GENERAL, "DPMS is not supported.");
00057 }
00058 }
00059
00060 ~ScreenSaverX11Private()
00061 {
00062 delete m_resetTimer;
00063 }
00064
00065 bool IsScreenSaverRunning()
00066 {
00067 return m_xscreensaverRunning || m_gscreensaverRunning;
00068 }
00069
00070 bool IsDPMSEnabled() { return m_dpmsenabled; }
00071
00072 void StopTimer() { if (m_resetTimer) m_resetTimer->stop(); }
00073
00074 void StartTimer()
00075 {
00076 if (m_resetTimer)
00077 m_resetTimer->start(m_timeoutInterval, FALSE);
00078 }
00079
00080 void ResetTimer()
00081 {
00082 StopTimer();
00083
00084 if (m_timeoutInterval == -1)
00085 {
00086 m_timeoutInterval = gContext->GetNumSettingOnHost(
00087 "xscreensaverInterval", gContext->GetHostName(), 50) * 1000;
00088 }
00089
00090 if (m_timeoutInterval > 0)
00091 StartTimer();
00092 }
00093
00094
00095 bool DeactivatedDPMS() { return m_dpmsdeactivated; }
00096
00097 void DisableDPMS()
00098 {
00099 if (IsDPMSEnabled())
00100 {
00101 m_dpmsdeactivated = true;
00102 DPMSDisable(qt_xdisplay());
00103 VERBOSE(VB_GENERAL, "DPMS Deactivated ");
00104 }
00105 }
00106
00107 void RestoreDPMS()
00108 {
00109 if (m_dpmsdeactivated)
00110 {
00111 m_dpmsdeactivated = false;
00112 DPMSEnable(qt_xdisplay());
00113 VERBOSE(VB_GENERAL, "DPMS Reactivated.");
00114 }
00115 }
00116
00117 void SaveScreenSaver()
00118 {
00119 if (!m_state.saved)
00120 {
00121 XGetScreenSaver(qt_xdisplay(), &m_state.timeout, &m_state.interval,
00122 &m_state.preferblank, &m_state.allowexposure);
00123 m_state.saved = true;
00124 }
00125 }
00126
00127 void RestoreScreenSaver()
00128 {
00129 if (m_state.saved)
00130 {
00131 XSetScreenSaver(qt_xdisplay(), m_state.timeout, m_state.interval,
00132 m_state.preferblank, m_state.allowexposure);
00133 m_state.saved = false;
00134 }
00135 }
00136
00137 void ResetScreenSaver()
00138 {
00139 if (IsScreenSaverRunning())
00140 {
00141 QDateTime current_time = QDateTime::currentDateTime ();
00142 if ((!m_last_deactivated.isValid()) ||
00143 (m_last_deactivated.secsTo(current_time) > 30))
00144 {
00145 if (m_xscreensaverRunning)
00146 myth_system("xscreensaver-command -deactivate >&- 2>&- &");
00147 else if (m_gscreensaverRunning)
00148 myth_system("gnome-screensaver-command --poke >&- 2>&- &");
00149 m_last_deactivated = current_time;
00150 }
00151 }
00152 }
00153
00154 private:
00155 struct ScreenSaverState
00156 {
00157 ScreenSaverState() : saved(false) {}
00158 bool saved;
00159 int timeout;
00160 int interval;
00161 int preferblank;
00162 int allowexposure;
00163 };
00164
00165 private:
00166 bool m_dpmsaware;
00167 bool m_xscreensaverRunning;
00168 bool m_gscreensaverRunning;
00169 BOOL m_dpmsenabled;
00170 bool m_dpmsdeactivated;
00171
00172 int m_timeoutInterval;
00173 QTimer *m_resetTimer;
00174
00175 QDateTime m_last_deactivated;
00176
00177 ScreenSaverState m_state;
00178 };
00179
00180 ScreenSaverX11::ScreenSaverX11()
00181 {
00182 d = new ScreenSaverX11Private(this);
00183 }
00184
00185 ScreenSaverX11::~ScreenSaverX11()
00186 {
00187
00188 if (d->DeactivatedDPMS())
00189 Restore();
00190
00191 delete d;
00192 }
00193
00194 void ScreenSaverX11::Disable(void)
00195 {
00196 d->SaveScreenSaver();
00197 XResetScreenSaver(qt_xdisplay());
00198
00199 XSetScreenSaver(qt_xdisplay(), 0, 0, 0, 0);
00200
00201 d->DisableDPMS();
00202
00203 if (d->IsScreenSaverRunning())
00204 d->ResetTimer();
00205 }
00206
00207 void ScreenSaverX11::Restore(void)
00208 {
00209 d->RestoreScreenSaver();
00210 d->RestoreDPMS();
00211
00212
00213 XResetScreenSaver(qt_xdisplay());
00214
00215 if (d->IsScreenSaverRunning())
00216 d->StopTimer();
00217 }
00218
00219 void ScreenSaverX11::Reset(void)
00220 {
00221 XResetScreenSaver(qt_xdisplay());
00222 if (d->IsScreenSaverRunning())
00223 resetSlot();
00224
00225 if (Asleep())
00226 {
00227 DPMSForceLevel(qt_xdisplay(), DPMSModeOn);
00228
00229
00230 XSync(qt_xdisplay(), false);
00231 }
00232 }
00233
00234 bool ScreenSaverX11::Asleep(void)
00235 {
00236 if (!d->IsDPMSEnabled())
00237 return false;
00238
00239 if (d->DeactivatedDPMS())
00240 return false;
00241
00242 BOOL on;
00243 CARD16 power_level;
00244
00245 DPMSInfo(qt_xdisplay(), &power_level, &on);
00246
00247 return (power_level != DPMSModeOn);
00248 }
00249
00250 void ScreenSaverX11::resetSlot()
00251 {
00252 d->ResetScreenSaver();
00253 }