Skip to content

Instantly share code, notes, and snippets.

@Vineg
Last active April 10, 2024 20:10
Show Gist options
  • Save Vineg/eca223fbf478a3c806444a13e538a9fc to your computer and use it in GitHub Desktop.
Save Vineg/eca223fbf478a3c806444a13e538a9fc to your computer and use it in GitHub Desktop.
Cross platform tool to prevent operating system from sleep after long inactive time (usually named Inhibitor). Requires QT DBus library for communication on Linux OS
#include "suspend_inhibitor.h"
#ifdef __APPLE__
#include <IOKit/pwr_mgt/IOPMLib.h>
#elif defined(_WIN32)
#include <Windows.h>
#elif defined(__linux__)
#include <QtDBus/QtDBus>
#endif
#include <iostream>
namespace {
#ifdef __linux__
class LinuxSuspendInhibitor {
public:
LinuxSuspendInhibitor() : bus_(QDBusConnection::sessionBus())
{
if (bus_.isConnected())
available_dbus_services_ = bus_.interface()->registeredServiceNames().value();
}
template <typename T>
void logReply(const QDBusReply<T> &reply) const;
void inhibit(bool enable, uint32_t *cookies) const;
private:
const QDBusConnection bus_;
QStringList available_dbus_services_;
};
template<>
void LinuxSuspendInhibitor::logReply(const QDBusReply<void> &reply) const {
if (reply.isValid())
{
std::cout << "succesful" << std::endl;
} else {
QDBusError error = reply.error();
std::cout << error.message().toStdString() << error.name().toStdString() << std::endl;
}
}
template <typename T>
void LinuxSuspendInhibitor::logReply(const QDBusReply<T> &reply) const
{
if (reply.isValid())
{
std::cout << "succesful: " << reply << std::endl;
} else {
QDBusError error = reply.error();
std::cout << error.message().toStdString() << error.name().toStdString() << std::endl;
}
}
void LinuxSuspendInhibitor::inhibit(bool enable, uint32_t *cookies) const
{
if(bus_.isConnected()) {
QString services[MAX_SERVICES] = {
"org.gnome.SessionManager"
};
QString paths[MAX_SERVICES] = {
"/org/gnome/SessionManager"
};
for (int i = 0; i < MAX_SERVICES; i++) {
if (!available_dbus_services_.contains(services[i]))
continue;
QDBusInterface sessionManagerInterface(services[i], paths[i], services[i], bus_);
if (!sessionManagerInterface.isValid())
continue;
uint32_t xid = 0;
uint32_t flags = 0x4; // Inhibit suspending the session or computer
if (enable) {
QDBusReply<unsigned int> reply;
reply = sessionManagerInterface.call("Inhibit", "Metashape", xid, "Processing", flags);
cookies[i] = reply.value();
// logReply(reply);
} else {
QDBusReply<void> reply;
reply = sessionManagerInterface.call("Uninhibit", cookies[i]);
// logReply(reply);
}
}
}
}
const LinuxSuspendInhibitor linux_inhibitor_ = LinuxSuspendInhibitor();
#endif
}
void SuspendInhibitor::inhibit(bool enable)
{
// Prevent OS from suspending
#if defined(_WIN32)
SetThreadExecutionState(ES_CONTINUOUS | (enable ? ES_SYSTEM_REQUIRED : 0));
#elif defined(__APPLE__)
if (enable) {
CFStringRef name = CFSTR("Metashape processing");
if (IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleSystemSleep,
kIOPMAssertionLevelOn, name,
&s_power_assertion_) != kIOReturnSuccess) {
s_power_assertion_ = kIOPMNullAssertionID;
}
} else {
if (s_power_assertion_ != kIOPMNullAssertionID) {
IOPMAssertionRelease(s_power_assertion_);
s_power_assertion_ = kIOPMNullAssertionID;
}
}
#elif defined(__linux__)
linux_inhibitor_.inhibit(enable, cookies_);
#endif
}
#pragma once
#ifdef __APPLE__
#include <IOKit/pwr_mgt/IOPMLib.h>
#endif
namespace {
#ifdef __linux__
const int MAX_SERVICES = 1;
#endif
}
class SuspendInhibitor {
public:
SuspendInhibitor() { inhibit(true); }
~SuspendInhibitor() { inhibit(false); }
private:
void inhibit(bool enable);
#if defined(__APPLE__)
IOPMAssertionID s_power_assertion_ = kIOPMNullAssertionID;
#elif defined(__linux__)
unsigned int cookies_[MAX_SERVICES];
#endif
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment