0

The question

Is there a method to prevent an X session from starting the screensaver, going into power save mode, or performing a screen blank from code?

What I'm working with

Language: C/C++ GUI framework: GTK3 Hardware: Raspberry Pi 3B Software: Raspbian 10 - Buster

My program needs to run on screen for long periods (up to 12 hours) with the GUI running without user interaction. The GUI acts as a status monitor for systems in field (if the screen goes black, something went wrong).

What I know

GTK3 can determine if the screensaver is active

GTK3 has a boolean property to report if the screensaver of the system is active (see here), but no other references are made in the documentation.

Raspbian uses screen blanking

Raspbian does not come installed with xscreensaver or other package to control the screen off time. Instead, it relies mostly on X to "blank screen". This can be managed with the xset command as a superuser. The canonical way to do this is reported in the hardware-specific Stack Exchange (here).

End-users cannot be trusted

In my case, the program will be used by folks who are barely computer literate. The result must be user-friendly and not expect the user to ever touch a terminal, let alone to make permanent changes to the startup config of X. While one option would be to distribute the program as a customized Raspbian disk image, I would like to explore other options.

I need to see an example

While there were some places to start using this question, implementing them is problematic. When I attempt to use the following MWE with and without the commented line, nothing happens. I cannot simulate the screen blanking function.

#include <X11/extensions/scrnsaver.h>

int main() {
    // XScreenSaverSuspend;
    XForceScreenSaver;
    usleep(1000000);
    return 0;
}
WesH
  • 460
  • 5
  • 15

2 Answers2

2

You have to pass parameters to the function:

void XScreenSaverSuspend(Display *dpy, Bool suspend);
#include <X11/extensions/scrnsaver.h>

int main() {
    XScreenSaverSuspend (display, True);
    usleep(1000000);
    return 0;
}

But I don't think you have time to see the result with this program and when program ends the screensaver goes back to its previous state.

For your GTK framework, you can obtain the Display use:

Display *
gdk_x11_display_get_xdisplay (GdkDisplay *display);

Docs here.

For X:

/* use the information from the environment variable DISPLAY 
   to create the X connection:
*/  
Display * dis = XOpenDisplay((char *)0); // or ":0.0"
Manuel
  • 2,526
  • 1
  • 13
  • 17
  • The short time should be solved by the commented line in my MWE. But how do I pull in the ``display``? Say the address of my display is ``:0``, how do I convey that to the code? Being lazy and casting an ``int 0`` there gives me angry error messages. I'm having some trouble finding how to pull that value from the esoteric documentation of X11. – WesH Jul 09 '20 at 21:21
  • Thanks for the useful edit. Unfortunately, this method does not seem to produce results. While I can run X11 header commands without errors, it does not seem to have any effect on the real screen states or the values reported by ``xset``. – WesH Jul 10 '20 at 20:36
1

A hacky, OS-specific solution:

Raspbian does not appear to require super user elevation to modify the xset. Adding the line to the code:

system("xset -dpms");
system("xset s off");

is sufficient to turn off the power management settings and the screensaver.

This is obviously sloppy, and it potentially leaves the OS in an undesirable state if the program breaks before these have a chance to be reset to default values. More elegant answers are encouraged.

WesH
  • 460
  • 5
  • 15