diff options
Diffstat (limited to 'kcontrol/energy/energy.cpp')
-rw-r--r-- | kcontrol/energy/energy.cpp | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/kcontrol/energy/energy.cpp b/kcontrol/energy/energy.cpp new file mode 100644 index 000000000..af3c4965d --- /dev/null +++ b/kcontrol/energy/energy.cpp @@ -0,0 +1,442 @@ +/* vi: ts=8 sts=4 sw=4 + * + * + * + * This file is part of the KDE project, module kcontrol. + * Copyright (C) 1999 Geert Jansen <g.t.jansen@stud.tue.nl> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + * + * Based on kcontrol1 energy.cpp, Copyright (c) 1999 Tom Vijlbrief + */ + + +/* + * KDE Energy setup module. + */ + +#include <config.h> + +#if !defined(QT_CLEAN_NAMESPACE) +#define QT_CLEAN_NAMESPACE +#endif + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qwhatsthis.h> + +#include <kconfig.h> +#include <kcursor.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <knuminput.h> +#include <krun.h> +#include <kstandarddirs.h> +#include <kurllabel.h> + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> + +#include "energy.h" + + +#ifdef HAVE_DPMS +#include <X11/Xmd.h> +extern "C" { +#include <X11/extensions/dpms.h> +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +Bool DPMSCapable( Display * ); +int __kde_do_not_unload = 1; + +#ifndef HAVE_DPMSCAPABLE_PROTO +Bool DPMSCapable ( Display * ); +#endif + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} + +#if defined(XIMStringConversionRetrival) || defined (__sun) || defined(__hpux) +extern "C" { +#endif + Bool DPMSQueryExtension(Display *, int *, int *); + Status DPMSEnable(Display *); + Status DPMSDisable(Display *); + Bool DPMSGetTimeouts(Display *, CARD16 *, CARD16 *, CARD16 *); + Bool DPMSSetTimeouts(Display *, CARD16, CARD16, CARD16); +#if defined(XIMStringConversionRetrival) || defined (__sun) || defined(__hpux) +} +#endif +#endif + +static const int DFLT_STANDBY = 0; +static const int DFLT_SUSPEND = 30; +static const int DFLT_OFF = 60; + + +/**** DLL Interface ****/ + +extern "C" { + + KDE_EXPORT KCModule *create_energy(QWidget *parent, char *) { + return new KEnergy(parent, "kcmenergy"); + } + + KDE_EXPORT void init_energy() { +#ifdef HAVE_DPMS + KConfig *cfg = new KConfig("kcmdisplayrc", true /*readonly*/, false /*no globals*/); + cfg->setGroup("DisplayEnergy"); + + Display *dpy = qt_xdisplay(); + CARD16 pre_configured_status; + BOOL pre_configured_enabled; + CARD16 pre_configured_standby; + CARD16 pre_configured_suspend; + CARD16 pre_configured_off; + bool enabled; + CARD16 standby; + CARD16 suspend; + CARD16 off; + int dummy; + /* query the running X server if DPMS is supported */ + if (DPMSQueryExtension(dpy, &dummy, &dummy) && DPMSCapable(dpy)) { + DPMSGetTimeouts(dpy, &pre_configured_standby, &pre_configured_suspend, &pre_configured_off); + DPMSInfo(dpy, &pre_configured_status, &pre_configured_enabled); + /* let the user override the settings */ + enabled = cfg->readBoolEntry("displayEnergySaving", pre_configured_enabled); + standby = cfg->readNumEntry("displayStandby", pre_configured_standby/60); + suspend = cfg->readNumEntry("displaySuspend", pre_configured_suspend/60); + off = cfg->readNumEntry("displayPowerOff", pre_configured_off/60); + } else { + /* provide our defauts */ + enabled = true; + standby = DFLT_STANDBY; + suspend = DFLT_SUSPEND; + off = DFLT_OFF; + } + + delete cfg; + + KEnergy::applySettings(enabled, standby, suspend, off); +#endif + } +} + +/**** KEnergy ****/ + +KEnergy::KEnergy(QWidget *parent, const char *name) + : KCModule(parent, name) +{ + m_bChanged = false; + m_bEnabled = false; + m_Standby = DFLT_STANDBY; + m_Suspend = DFLT_SUSPEND; + m_Off = DFLT_OFF; + m_bDPMS = false; + m_bMaintainSanity = true; + + setQuickHelp( i18n("<h1>Display Power Control</h1> If your display supports" + " power saving features, you can configure them using this module.<p>" + " There are three levels of power saving: standby, suspend, and off." + " The greater the level of power saving, the longer it takes for the" + " display to return to an active state.<p>" + " To wake up the display from a power saving mode, you can make a small" + " movement with the mouse, or press a key that is not likely to cause" + " any unintentional side-effects, for example, the \"Shift\" key.")); + +#ifdef HAVE_DPMS + int dummy; + m_bDPMS = DPMSQueryExtension(qt_xdisplay(), &dummy, &dummy); +#endif + + QVBoxLayout *top = new QVBoxLayout(this, 0, KDialog::spacingHint()); + QHBoxLayout *hbox = new QHBoxLayout(); + top->addLayout(hbox); + + QLabel *lbl; + if (m_bDPMS) { + m_pCBEnable= new QCheckBox(i18n("&Enable display power management" ), this); + connect(m_pCBEnable, SIGNAL(toggled(bool)), SLOT(slotChangeEnable(bool))); + hbox->addWidget(m_pCBEnable); + QWhatsThis::add( m_pCBEnable, i18n("Check this option to enable the" + " power saving features of your display.") ); + } else { + lbl = new QLabel(i18n("Your display does not support power saving."), this); + hbox->addWidget(lbl); + } + + KURLLabel *logo = new KURLLabel(this); + logo->setURL("http://www.energystar.gov"); + logo->setPixmap(QPixmap(locate("data", "kcontrol/pics/energybig.png"))); + logo->setTipText(i18n("Learn more about the Energy Star program")); + logo->setUseTips(true); +connect(logo, SIGNAL(leftClickedURL(const QString&)), SLOT(openURL(const QString &))); + + hbox->addStretch(); + hbox->addWidget(logo); + + // Sliders + m_pStandbySlider = new KIntNumInput(m_Standby, this); + m_pStandbySlider->setLabel(i18n("&Standby after:")); + m_pStandbySlider->setRange(0, 120, 10); + m_pStandbySlider->setSuffix(i18n(" min")); + m_pStandbySlider->setSpecialValueText(i18n("Disabled")); + connect(m_pStandbySlider, SIGNAL(valueChanged(int)), SLOT(slotChangeStandby(int))); + top->addWidget(m_pStandbySlider); + QWhatsThis::add( m_pStandbySlider, i18n("Choose the period of inactivity" + " after which the display should enter \"standby\" mode. This is the" + " first level of power saving.") ); + + m_pSuspendSlider = new KIntNumInput(m_pStandbySlider, m_Suspend, this); + m_pSuspendSlider->setLabel(i18n("S&uspend after:")); + m_pSuspendSlider->setRange(0, 120, 10); + m_pSuspendSlider->setSuffix(i18n(" min")); + m_pSuspendSlider->setSpecialValueText(i18n("Disabled")); + connect(m_pSuspendSlider, SIGNAL(valueChanged(int)), SLOT(slotChangeSuspend(int))); + top->addWidget(m_pSuspendSlider); + QWhatsThis::add( m_pSuspendSlider, i18n("Choose the period of inactivity" + " after which the display should enter \"suspend\" mode. This is the" + " second level of power saving, but may not be different from the first" + " level for some displays.") ); + + m_pOffSlider = new KIntNumInput(m_pSuspendSlider, m_Off, this); + m_pOffSlider->setLabel(i18n("&Power off after:")); + m_pOffSlider->setRange(0, 120, 10); + m_pOffSlider->setSuffix(i18n(" min")); + m_pOffSlider->setSpecialValueText(i18n("Disabled")); + connect(m_pOffSlider, SIGNAL(valueChanged(int)), SLOT(slotChangeOff(int))); + top->addWidget(m_pOffSlider); + QWhatsThis::add( m_pOffSlider, i18n("Choose the period of inactivity" + " after which the display should be powered off. This is the" + " greatest level of power saving that can be achieved while the" + " display is still physically turned on.") ); + + top->addStretch(); + + if (m_bDPMS) + setButtons( KCModule::Help | KCModule::Default | KCModule::Apply ); + else + setButtons( KCModule::Help ); + + m_pConfig = new KConfig("kcmdisplayrc", false /*readwrite*/, false /*no globals*/); + m_pConfig->setGroup("DisplayEnergy"); + + load(); +} + + +KEnergy::~KEnergy() +{ + delete m_pConfig; +} + + +void KEnergy::load() +{ + load( false ); +} + +void KEnergy::load( bool useDefaults ) +{ + m_pConfig->setReadDefaults( useDefaults ); + readSettings(); + showSettings(); + + emit changed( useDefaults ); +} + + +void KEnergy::save() +{ + writeSettings(); + applySettings(m_bEnabled, m_Standby, m_Suspend, m_Off); + + emit changed(false); +} + + +void KEnergy::defaults() +{ + load( true ); +} + + +void KEnergy::readSettings() +{ + m_bEnabled = m_pConfig->readBoolEntry("displayEnergySaving", false); + m_Standby = m_pConfig->readNumEntry("displayStandby", DFLT_STANDBY); + m_Suspend = m_pConfig->readNumEntry("displaySuspend", DFLT_SUSPEND); + m_Off = m_pConfig->readNumEntry("displayPowerOff", DFLT_OFF); + + m_StandbyDesired = m_Standby; + m_SuspendDesired = m_Suspend; + m_OffDesired = m_Off; + + m_bChanged = false; +} + + +void KEnergy::writeSettings() +{ + if (!m_bChanged) + return; + + m_pConfig->writeEntry( "displayEnergySaving", m_bEnabled); + m_pConfig->writeEntry("displayStandby", m_Standby); + m_pConfig->writeEntry("displaySuspend", m_Suspend); + m_pConfig->writeEntry("displayPowerOff", m_Off); + + m_pConfig->sync(); + m_bChanged = false; +} + + +void KEnergy::showSettings() +{ + m_bMaintainSanity = false; + + if (m_bDPMS) + m_pCBEnable->setChecked(m_bEnabled); + + m_pStandbySlider->setEnabled(m_bEnabled); + m_pStandbySlider->setValue(m_Standby); + m_pSuspendSlider->setEnabled(m_bEnabled); + m_pSuspendSlider->setValue(m_Suspend); + m_pOffSlider->setEnabled(m_bEnabled); + m_pOffSlider->setValue(m_Off); + + m_bMaintainSanity = true; +} + + +extern "C" { + int dropError(Display *, XErrorEvent *); + typedef int (*XErrFunc) (Display *, XErrorEvent *); +} + +int dropError(Display *, XErrorEvent *) +{ + return 0; +} + +/* static */ +void KEnergy::applySettings(bool enable, int standby, int suspend, int off) +{ +#ifdef HAVE_DPMS + XErrFunc defaultHandler; + defaultHandler = XSetErrorHandler(dropError); + + Display *dpy = qt_xdisplay(); + + int dummy; + bool hasDPMS = DPMSQueryExtension(dpy, &dummy, &dummy); + if (hasDPMS) { + if (enable) { + DPMSEnable(dpy); + DPMSSetTimeouts(dpy, 60*standby, 60*suspend, 60*off); + } else + DPMSDisable(dpy); + } else + qWarning("Server has no DPMS extension"); + + XFlush(dpy); + XSetErrorHandler(defaultHandler); +#else + /* keep gcc silent */ + if (enable | standby | suspend | off) + /* nothing */ ; +#endif +} + + +void KEnergy::slotChangeEnable(bool ena) +{ + m_bEnabled = ena; + m_bChanged = true; + + m_pStandbySlider->setEnabled(ena); + m_pSuspendSlider->setEnabled(ena); + m_pOffSlider->setEnabled(ena); + + emit changed(true); +} + + +void KEnergy::slotChangeStandby(int value) +{ + m_Standby = value; + + if ( m_bMaintainSanity ) { + m_bMaintainSanity = false; + m_StandbyDesired = value; + if ((m_Suspend > 0 && m_Standby > m_Suspend) || + (m_SuspendDesired && m_Standby >= m_SuspendDesired) ) + m_pSuspendSlider->setValue(m_Standby); + if ((m_Off > 0 && m_Standby > m_Off) || + (m_OffDesired && m_Standby >= m_OffDesired) ) + m_pOffSlider->setValue(m_Standby); + m_bMaintainSanity = true; + } + + m_bChanged = true; + emit changed(true); +} + + +void KEnergy::slotChangeSuspend(int value) +{ + m_Suspend = value; + + if ( m_bMaintainSanity ) { + m_bMaintainSanity = false; + m_SuspendDesired = value; + if (m_Suspend == 0 && m_StandbyDesired > 0) + m_pStandbySlider->setValue( m_StandbyDesired ); + else if (m_Suspend < m_Standby || m_Suspend <= m_StandbyDesired ) + m_pStandbySlider->setValue(m_Suspend); + if ((m_Off > 0 && m_Suspend > m_Off) || + (m_OffDesired && m_Suspend >= m_OffDesired) ) + m_pOffSlider->setValue(m_Suspend); + m_bMaintainSanity = true; + } + + m_bChanged = true; + emit changed(true); +} + + +void KEnergy::slotChangeOff(int value) +{ + m_Off = value; + + if ( m_bMaintainSanity ) { + m_bMaintainSanity = false; + m_OffDesired = value; + if (m_Off == 0 && m_StandbyDesired > 0) + m_pStandbySlider->setValue( m_StandbyDesired ); + else if (m_Off < m_Standby || m_Off <= m_StandbyDesired ) + m_pStandbySlider->setValue(m_Off); + if (m_Off == 0 && m_SuspendDesired > 0) + m_pSuspendSlider->setValue( m_SuspendDesired ); + else if (m_Off < m_Suspend || m_Off <= m_SuspendDesired ) + m_pSuspendSlider->setValue(m_Off); + m_bMaintainSanity = true; + } + + m_bChanged = true; + emit changed(true); +} + +void KEnergy::openURL(const QString &URL) +{ + new KRun(KURL( URL )); +} + +#include "energy.moc" |