mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-25 11:22:52 +00:00
233 lines
7.2 KiB
C++
233 lines
7.2 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
|
|
***************************************************************************/
|
|
|
|
|
|
#include "powerdevildpmsaction.h"
|
|
|
|
#include <powerdevilcore.h>
|
|
|
|
#include <config-workspace.h>
|
|
|
|
#include <QtGui/qx11info_x11.h>
|
|
|
|
#include <KConfigGroup>
|
|
#include <KDebug>
|
|
#include <KPluginFactory>
|
|
|
|
#include <X11/Xmd.h>
|
|
#include <X11/X.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xos.h>
|
|
extern "C" {
|
|
#include <X11/extensions/dpms.h>
|
|
int __kde_do_not_unload = 1;
|
|
|
|
#ifndef HAVE_DPMSCAPABLE_PROTO
|
|
Bool DPMSCapable(Display *);
|
|
#endif
|
|
|
|
#ifndef HAVE_DPMSINFO_PROTO
|
|
Status DPMSInfo(Display *, CARD16 *, BOOL *);
|
|
#endif
|
|
|
|
int dropError(Display *, XErrorEvent *);
|
|
typedef int (*XErrFunc)(Display *, XErrorEvent *);
|
|
}
|
|
|
|
int dropError(Display *, XErrorEvent *)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
class PowerDevilDPMSAction::Private
|
|
{
|
|
public:
|
|
XErrorHandler defaultHandler;
|
|
};
|
|
|
|
K_PLUGIN_FACTORY(PowerDevilDPMSActionFactory, registerPlugin<PowerDevilDPMSAction>(); )
|
|
K_EXPORT_PLUGIN(PowerDevilDPMSActionFactory("powerdevildpmsaction"))
|
|
|
|
PowerDevilDPMSAction::PowerDevilDPMSAction(QObject* parent, const QVariantList &args)
|
|
: Action(parent)
|
|
, m_idleTime(0)
|
|
, m_inhibitScreen(0) // can't use PowerDevil::PolicyAgent enum because X11/X.h defines None as 0L
|
|
, d(new Private)
|
|
{
|
|
setRequiredPolicies(PowerDevil::PolicyAgent::ChangeScreenSettings);
|
|
|
|
// We want to query for DPMS in the constructor, before anything else happens
|
|
d->defaultHandler = XSetErrorHandler(dropError);
|
|
|
|
// Since we are in the constructor, we should check for support manually
|
|
if (!isSupported()) {
|
|
XSetErrorHandler(d->defaultHandler);
|
|
return;
|
|
}
|
|
|
|
// Is the action being loaded outside the core?
|
|
if (args.size() > 0) {
|
|
if (args.first().toBool()) {
|
|
kDebug() << "Action loaded from outside the core, skipping early init";
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Pretend we're unloading profiles here, as if the action is not enabled, DPMS should be switched off.
|
|
onProfileUnload();
|
|
|
|
// Listen to the policy agent
|
|
connect(PowerDevil::PolicyAgent::instance(),
|
|
SIGNAL(unavailablePoliciesChanged(PowerDevil::PolicyAgent::RequiredPolicies)),
|
|
this,
|
|
SLOT(onUnavailablePoliciesChanged(PowerDevil::PolicyAgent::RequiredPolicies)));
|
|
// inhibitions persist over kded module unload/load
|
|
m_inhibitScreen = PowerDevil::PolicyAgent::instance()->unavailablePolicies() & PowerDevil::PolicyAgent::ChangeScreenSettings;
|
|
}
|
|
|
|
PowerDevilDPMSAction::~PowerDevilDPMSAction()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
bool PowerDevilDPMSAction::isSupported()
|
|
{
|
|
Display *dpy = QX11Info::display();
|
|
int dummy;
|
|
|
|
return DPMSQueryExtension(dpy, &dummy, &dummy) && DPMSCapable(dpy);
|
|
}
|
|
|
|
void PowerDevilDPMSAction::onProfileUnload()
|
|
{
|
|
using namespace PowerDevil;
|
|
Display *dpy = QX11Info::display();
|
|
if (!(PolicyAgent::instance()->unavailablePolicies() & PolicyAgent::ChangeScreenSettings)) {
|
|
DPMSDisable(dpy);
|
|
} else {
|
|
kDebug() << "Not performing DPMS action due to inhibition";
|
|
}
|
|
DPMSSetTimeouts(dpy, 0, 0, 0);
|
|
}
|
|
|
|
void PowerDevilDPMSAction::onWakeupFromIdle()
|
|
{
|
|
//
|
|
}
|
|
|
|
void PowerDevilDPMSAction::onIdleTimeout(int msec)
|
|
{
|
|
Q_UNUSED(msec);
|
|
}
|
|
|
|
void PowerDevilDPMSAction::onProfileLoad()
|
|
{
|
|
using namespace PowerDevil;
|
|
Display *dpy = QX11Info::display();
|
|
if (!(PolicyAgent::instance()->unavailablePolicies() & PolicyAgent::ChangeScreenSettings)) {
|
|
DPMSEnable(dpy);
|
|
} else {
|
|
kDebug() << "Not performing DPMS action due to inhibition";
|
|
return;
|
|
}
|
|
|
|
XFlush(dpy);
|
|
XSetErrorHandler(d->defaultHandler);
|
|
|
|
// An unloaded action will have m_idleTime = 0:
|
|
// DPMS enabled with zeroed timeouts is effectively disabled.
|
|
// So onProfileLoad is always safe
|
|
DPMSSetTimeouts(dpy, (CARD16)m_idleTime, (CARD16)(m_idleTime * 1.5), (CARD16)(m_idleTime * 2));
|
|
|
|
XFlush(dpy);
|
|
XSetErrorHandler(d->defaultHandler);
|
|
}
|
|
|
|
void PowerDevilDPMSAction::triggerImpl(const QVariantMap& args)
|
|
{
|
|
CARD16 dummy;
|
|
BOOL enabled;
|
|
Display *dpy = QX11Info::display();
|
|
DPMSInfo(dpy, &dummy, &enabled);
|
|
|
|
if (args["Type"].toString() == "TurnOff") {
|
|
if (enabled) {
|
|
DPMSForceLevel(dpy, DPMSModeOff);
|
|
} else {
|
|
DPMSEnable(dpy);
|
|
DPMSForceLevel(dpy, DPMSModeOff);
|
|
}
|
|
} else if (args["Type"].toString() == "Standby") {
|
|
if (enabled) {
|
|
DPMSForceLevel(dpy, DPMSModeStandby);
|
|
} else {
|
|
DPMSEnable(dpy);
|
|
DPMSForceLevel(dpy, DPMSModeStandby);
|
|
}
|
|
} else if (args["Type"].toString() == "Suspend") {
|
|
if (enabled) {
|
|
DPMSForceLevel(dpy, DPMSModeSuspend);
|
|
} else {
|
|
DPMSEnable(dpy);
|
|
DPMSForceLevel(dpy, DPMSModeSuspend);
|
|
}
|
|
}
|
|
|
|
// this leaves DPMS enabled but if it's meant to be disabled
|
|
// then the timeouts will be zero and so effectively disabled
|
|
}
|
|
|
|
bool PowerDevilDPMSAction::loadAction(const KConfigGroup& config)
|
|
{
|
|
m_idleTime = config.readEntry<int>("idleTime", -1);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PowerDevilDPMSAction::onUnloadAction()
|
|
{
|
|
m_idleTime = 0;
|
|
return Action::onUnloadAction();
|
|
}
|
|
|
|
void PowerDevilDPMSAction::onUnavailablePoliciesChanged(PowerDevil::PolicyAgent::RequiredPolicies policies)
|
|
{
|
|
// only take action if screen inhibit changed
|
|
PowerDevil::PolicyAgent::RequiredPolicies oldPolicy = m_inhibitScreen;
|
|
m_inhibitScreen = policies & PowerDevil::PolicyAgent::ChangeScreenSettings;
|
|
if (oldPolicy == m_inhibitScreen) {
|
|
return;
|
|
}
|
|
|
|
if (m_inhibitScreen) {
|
|
// Inhibition triggered: disable DPMS
|
|
kDebug() << "Disabling DPMS due to inhibition";
|
|
Display *dpy = QX11Info::display();
|
|
DPMSSetTimeouts(dpy, 0, 0, 0);
|
|
DPMSDisable(dpy); // wakes the screen - do we want this?
|
|
} else {
|
|
// Inhibition removed: let's start again
|
|
onProfileLoad();
|
|
kDebug() << "Restoring DPMS features after inhibition release";
|
|
}
|
|
}
|
|
|
|
#include "moc_powerdevildpmsaction.cpp"
|