1
Window / Switching to fullscreen with a separate thread that handles window game loop
« on: December 31, 2020, 04:08:56 pm »
I have a program that creates a window in a class constructor, then passes its reference to a thread that handles the main game loop. I then poll the window events in the class constructor.
I'd like the window to go fullscreen when the user hits ctrl+F, and switch back to windowed when the hotkey is pressed again, and I've tried doing so by using
Should I just close the window and recreate the thread? Is there a way to avoid that?
Class constructor:
Game loop part that processes the events, which should be fine:
The whole file, but without the fullscreen stuff: https://github.com/Elanif/NESTRIS/blob/master/src/Window.cpp
Edit: I'm pretty sure the problem was the lack of mutexes and lock guards. After guarding some calls to Window::isOpen, clear, draw, display, it almost always works, except for a few times when the window turns completely black. In that case it still responds to events and it can be fixed by toggling fullscreen and back again.
I'd like the window to go fullscreen when the user hits ctrl+F, and switch back to windowed when the hotkey is pressed again, and I've tried doing so by using
window.create(sf::VideoMode::getFullscreenModes()[0], "NESTRIS", sf::Style::Fullscreen);
both in the events polling loop and the game loop thread with no avail. The tutorial says "Events must be polled in the window's thread" So I suppose the window should be recreated in the class constructor, but even resizing the window, without going fullscreen doesn't work: the window goes white and unresponseive.Should I just close the window and recreate the thread? Is there a way to avoid that?
Class constructor:
sf::RenderWindow window(sf::VideoMode(tilerend.width_pixels, tilerend.height_pixels), "NESTRIS");
window.setPosition(...);
window.setSize(...);
window.setActive(false);
std::thread render_thread(&Window::render, this, std::ref(window), std::ref(tilerend));
fullscreen.store(false);
sf::Event event;
bool is_mouse_hidden = false;
while (window.isOpen()&&!close_window) {
if (window.waitEvent(event)) {
if (!is_mouse_hidden && hide_cursor.load()) {
window.setMouseCursorVisible(false);
is_mouse_hidden = true;
}
else if (is_mouse_hidden && event.type==sf::Event::MouseMoved) {
window.setMouseCursorVisible(true);
is_mouse_hidden = false;
}
event_queue.push(event);
}
if (toggle_fullscreen.load()) {
toggle_fullscreen.store(false);
if (fullscreen.load()) {
fullscreen.store(false);
window.create(sf::VideoMode(window_size_x.load(), window_size_y.load()), "NESTRIS");
}
else {
fullscreen.store(true);
//even this doesn't work: window.create(sf::VideoMode(window_size_x.load()*1.2, window_size_y.load()*1.2), "NESTRIS");
window.create(sf::VideoMode::getFullscreenModes()[0], "NESTRIS", sf::Style::Fullscreen);
}
}
}
if (render_thread.joinable())
render_thread.join();
window.setActive(true);
window.close();
window.setPosition(...);
window.setSize(...);
window.setActive(false);
std::thread render_thread(&Window::render, this, std::ref(window), std::ref(tilerend));
fullscreen.store(false);
sf::Event event;
bool is_mouse_hidden = false;
while (window.isOpen()&&!close_window) {
if (window.waitEvent(event)) {
if (!is_mouse_hidden && hide_cursor.load()) {
window.setMouseCursorVisible(false);
is_mouse_hidden = true;
}
else if (is_mouse_hidden && event.type==sf::Event::MouseMoved) {
window.setMouseCursorVisible(true);
is_mouse_hidden = false;
}
event_queue.push(event);
}
if (toggle_fullscreen.load()) {
toggle_fullscreen.store(false);
if (fullscreen.load()) {
fullscreen.store(false);
window.create(sf::VideoMode(window_size_x.load(), window_size_y.load()), "NESTRIS");
}
else {
fullscreen.store(true);
//even this doesn't work: window.create(sf::VideoMode(window_size_x.load()*1.2, window_size_y.load()*1.2), "NESTRIS");
window.create(sf::VideoMode::getFullscreenModes()[0], "NESTRIS", sf::Style::Fullscreen);
}
}
}
if (render_thread.joinable())
render_thread.join();
window.setActive(true);
window.close();
Game loop part that processes the events, which should be fine:
while (event_queue.size() > 0)
{
sf::Event event = event_queue.pop();
switch (event.type) {
case sf::Event::Closed:
close_window.store(true);
break;
case sf::Event::KeyPressed: {
bool ctrl = sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl);
if (window.hasFocus()) {
if ((event.key.code == sf::Keyboard::F && ctrl)) {
toggle_fullscreen.store(true);
}
}
}
break;
case sf::Event::Resized:
if (!fullscreen.load()) {
window_size_x.store(window.getSize().x);
window_size_y.store(window.getSize().y);
}
break;
}
}
{
sf::Event event = event_queue.pop();
switch (event.type) {
case sf::Event::Closed:
close_window.store(true);
break;
case sf::Event::KeyPressed: {
bool ctrl = sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl);
if (window.hasFocus()) {
if ((event.key.code == sf::Keyboard::F && ctrl)) {
toggle_fullscreen.store(true);
}
}
}
break;
case sf::Event::Resized:
if (!fullscreen.load()) {
window_size_x.store(window.getSize().x);
window_size_y.store(window.getSize().y);
}
break;
}
}
The whole file, but without the fullscreen stuff: https://github.com/Elanif/NESTRIS/blob/master/src/Window.cpp
Edit: I'm pretty sure the problem was the lack of mutexes and lock guards. After guarding some calls to Window::isOpen, clear, draw, display, it almost always works, except for a few times when the window turns completely black. In that case it still responds to events and it can be fixed by toggling fullscreen and back again.