19
votes

While developing a small cross-platform game on C++, I got stuck with following issue: when players are playing with a USB gamepad without touching a keyboard or mouse, the computer sleeps automatically while they're playing.

In Windows, it can be done easily using SetThreadExecutionState function. In OS X, I think it can be done with UpdateSystemActivity but not tested yet.

But the problem is, in Linux there's nothing like a common API between DE's. I've found that in Gnome you can stop the auto-suspending by using DBus calls Inhibit() and Uninhibit(), but it works only for Gnome.

So, is there exists a programatically cross-DE way (or non-DE way, for example if user is using something like dwm or awesome wm) to prevent a Linux system (using Xorg and without root access of course) from sleeping or turning on screensaver without changing user configuration files?

PS: Don't think that it's too complicated, but don't know how unfortunately.

3
Sounds like the actual problem is that the OS doesn't see the "gamepad" as activity - should be fixed in the OS drivers.Mats Petersson
Mats is right. You should not go on and modify user settings. What is going to happen when your program crashes or I have to forcibly terminate it? I remember games messing up all kinds of settings like brightness/color of the desktop. Even if you fork, I might do a hard reset on the machine. Your approach should be interrupting the suspend, not disabling/enabling it.Etherealone
@Etherealone yep, I'm not going to modify user settings, but how to prevent it from suspending? I know that in X11 there is a XResetScreensaver function, but it's just a screen saver, not sleeping, right?FalconUA
I'm fighting the same problem (askubuntu.com/q/655531/171608). Is there an app to translate gamepad inputs into suspend-timer resets? Someone made one to keep the screensaver from kicking in (launchpad.net/~foresto/+archive/ubuntu/toys). But I can't find anything to keep from suspending while gaming with a gamepad on Linux.guttermonk
This sounds like something that Caffeine should handle, so I submitted a bug report: bugs.launchpad.net/caffeine/+bug/1530544 Please visit and click "This bug affects you."guttermonk

3 Answers

9
votes

From a quick look at how mplayer and SDL do it, there are two things you can do to prevent the screensaver from firing up:

  • Disable it for the duration of the program:
    • Using XScreenSaverSuspend
    • Using DBus, calling org.freedesktop.ScreenSaver.Inhibit
  • Ping it periodically:
    • Using XResetScreenSaver
    • Using DBus, calling org.freedesktop.ScreenSaver.SimulateUserActivity
3
votes

I'm using QTDBUS using that

QDBusConnection bus = QDBusConnection::sessionBus();
if(bus.isConnected())
{
    QString services[MAX_SERVICES] = {
        "org.freedesktop.ScreenSaver",
        "org.gnome.SessionManager"
    };
    QString paths[MAX_SERVICES] = {
        "/org/freedesktop/ScreenSaver",
        "/org/gnome/SessionManager"
    };

    for(int i = 0; i < MAX_SERVICES ; i++)
    {        
        QDBusInterface screenSaverInterface(
            services[i], paths[i],services[i], bus, this);
        if (!screenSaverInterface.isValid())
            continue;       

        QDBusReply<uint> reply = screenSaverInterface.call(
            "Inhibit", "YOUR_APP_NAME", "REASON");
        if (reply.isValid())
        {
            cookieID = reply.value();
            qDebug()<<"succesful"
        } else {   
            QDBusError error =reply.error();
            qDebug()<<error.message()<<error.name();   
        }
    }
}
2
votes

As far as I can tell, things with xdg in the name are the way to go for cross-desktop-environment functionality. There appears to be a commandline utility called xdg-screensaver. It seems to have a bunch of screensavers hardwired and then fall back to xset s off/xset s default, so you might want to just call it when it's installed, or fall back to copying part of its logic when it's not...