【问题标题】:SDL_PollEvent causes screen to wake up after xset dpms force offSDL_PollEvent 导致屏幕在 xset dpms 强制关闭后唤醒
【发布时间】:2016-10-07 10:06:38
【问题描述】:

我有一个程序可以使用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 &amp;&amp; xset -display :0.0 dpms force off"); 之后不久自动重新打开,在下一次调用重新打开之前。

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

【问题讨论】:

    标签: linux sdl-2


    【解决方案1】:

    致电SDL_EnableScreenSaver()

    More info:

    为什么 SDL 默认禁用我的屏幕保护程序?

    许多使用 SDL 的应用程序是游戏、屏保或媒体播放器 用户要么长时间观看某物 时间或使用操纵杆输入通常不会阻止 屏幕保护程序不会启动。

    您可以通过设置环境变量来禁用此行为: SDL_VIDEO_ALLOW_SCREENSAVER=1 这可以为用户全局设置或 在代码中基于每个应用程序。

    在 SDL 2.0.2 中,这也可以通过设置提示来更改 SDL_HINT_VIDEO_ALLOW_SCREENSAVER.

    此外,SDL 2.0 还提供了函数SDL_EnableScreenSaver()

    【讨论】:

      猜你喜欢
      • 2010-11-02
      • 1970-01-01
      • 2019-03-13
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      相关资源
      最近更新 更多