SDL_PollEvent causes screen to wake up after xset dpms force off


I have a program that turns the screen on and off with xset dpms force on/off and also calls SDL_PollEvent(&e) in a loop. After turning the display off with xset, any call to SDL_PollEvent causes the screen to wake up, even without any input. I can comment out the SDL_PollEvent call and it doesn’t happen. Is there something I need to do with an event or something to prevent the screen from turning on? Updated with minimal code to reproduce the problem:

#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <atomic>
#include <iostream>
#include <thread>
using namespace std;
atomic<bool> SCREEN_ON(true);
atomic<bool> RUNNING(true);
atomic<bool> SERVER_CONNECTED(false);

std::string exec(const char *cmd) {
  char buffer[128];
  std::string result = "";
  std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
  if (!pipe)
    throw std::runtime_error("popen() failed!");
  while (!feof(pipe.get())) {
    if (fgets(buffer, 128, pipe.get()) != NULL)
      result += buffer;
  return result;
double get_time() {
    static const Uint64 freq = SDL_GetPerformanceFrequency();
    static const Uint64 begin_time = SDL_GetPerformanceCounter();
    Uint64 current = SDL_GetPerformanceCounter();
    Uint64 elapsed = current - begin_time;
    return (double)elapsed / (double)freq;

void handle_input() {
  SDL_Event e;
  while (SDL_PollEvent(&e)){}

void monitor_thread() {  
    while (RUNNING) {
        double time = get_time();
        if (time < 15)
            SERVER_CONNECTED = false;
        else if (time < 35)
            SERVER_CONNECTED = true;
            SERVER_CONNECTED = false;

        cout << "server status: " << SERVER_CONNECTED << endl;
        cout << "screen_on status: " << SCREEN_ON << endl;


        if (SCREEN_ON && (!SERVER_CONNECTED)) {
            cout << "TURNING SCREEN OFF\n";
            SCREEN_ON = false;
            exec("sleep 1 && xset -display :0.0 dpms force off");
        if ((!SCREEN_ON) && SERVER_CONNECTED) {
            cout << "TURNING SCREEN ON\n";
            SCREEN_ON = true;
            exec("sleep 1 && xset -display :0.0 dpms force on");

int main(int argc, char *argv[]) {
  Uint32 initflags = SDL_INIT_TIMER | SDL_INIT_VIDEO;
  Uint32 window_flags =
  SDL_Window *window =
      SDL_CreateWindow("title", 25, 25, 800, 600, window_flags);
  SDL_GLContext gl_context = SDL_GL_CreateContext(window);
  thread update_thread(monitor_thread);
  glClearColor(1, 1, 0, 0);
  while (RUNNING) {
    if (!SCREEN_ON) {
      cout << "zzz...\n";
  return 0;

The screen will turn itself back on very shortly after exec("sleep 1 && xset -display :0.0 dpms force off");, before the next call to turn it back on.

Nevermind, SDL_PollEvent can only be called in the main thread.


Call SDL_EnableScreenSaver().

More info:

Why does SDL disable my screensaver by default?

Many applications using SDL are games or screensavers or media players
where the user is either watching something for an extended period of
time or using joystick input which generally does not prevent the
screensaver from kicking on.

You can disable this behavior by setting the environment variable:
SDL_VIDEO_ALLOW_SCREENSAVER=1 This can be set globally for the user or
on a per-application basis in code.

In SDL 2.0.2 this can also be changed by setting the hint

Additionally, SDL 2.0 provides the function SDL_EnableScreenSaver().

Answered By – genpfault

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published