c++ - SDL_PollEvent 导致屏幕在 xset dpms force off 后唤醒

标签 c++ linux x11 sdl-2

我有一个程序可以使用 xset dpms force on/off 打开和关闭屏幕,并且还可以循环调用 SDL_PollEvent(&e)。使用 xset 关闭显示器后,任何对 SDL_PollEvent 的调用都会导致屏幕唤醒,即使没有任何输入也是如此。我可以注释掉 SDL_PollEvent 调用,但它不会发生。我需要对某个事件做些什么或阻止屏幕打开吗?使用最少的代码更新以重现问题:

#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;
        else
            SERVER_CONNECTED = false;

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

        handle_input();
        SDL_Delay(1000);

        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;
  SDL_Init(initflags);
  Uint32 window_flags =
      SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_GRABBED;
  SDL_Window *window =
      SDL_CreateWindow("title", 25, 25, 800, 600, window_flags);
  SDL_SetRelativeMouseMode(SDL_TRUE);
  SDL_EnableScreenSaver();
  SDL_GLContext gl_context = SDL_GL_CreateContext(window);
  glewInit();
  thread update_thread(monitor_thread);
  glClearColor(1, 1, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT);
  while (RUNNING) {
    if (!SCREEN_ON) {
      cout << "zzz...\n";
      SDL_Delay(2000);
      continue;
    } 
    glClear(GL_COLOR_BUFFER_BIT);
    SDL_Delay(16);
    SDL_GL_SwapWindow(window);
  }
  return 0;
}

屏幕将在 exec("sleep 1 && xset -display :0.0 dpms force off"); 后不久自行重新打开,然后再调用以重新打开它.

没关系,SDL_PollEvent只能在主线程中调用。

最佳答案

调用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 SDL_HINT_VIDEO_ALLOW_SCREENSAVER.

Additionally, SDL 2.0 provides the function SDL_EnableScreenSaver().

关于c++ - SDL_PollEvent 导致屏幕在 xset dpms force off 后唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39914670/

相关文章:

opengl - GLX/GLEW 初始化顺序 catch-22 : GLXEW_ARB_create_context, glXCreateContextAttribsARB、glXCreateContext

linux - 如何在bash中将变量分配给同一目录中文件的不同扩展名

linux - 如何以编程方式切换到 compiz 中的特定窗口?

winforms - 单控制台应用程序 : Winforms Method Throws Exception On Linux Without X

c++ - MPI 运行时给出不正确的输出

linux - libtorrent 在 Python 3 中工作吗?

x11 - 任何人仍然直接使用 xlib 进行编程

c++ - 从类中返回可 move 的成员变量

c++ - 展开两个参数包

c++ - < token 之前的错误预期初始值设定项