【发布时间】: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 && xset -display :0.0 dpms force off"); 之后不久自动重新打开,在下一次调用重新打开之前。
没关系,SDL_PollEvent 只能在主线程中调用。
【问题讨论】: