我有一个程序可以使用 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只能在主线程中调用。
最佳答案
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/