SFML community forums

Help => Window => Topic started by: Elanif on December 31, 2020, 04:08:56 pm

Title: Switching to fullscreen with a separate thread that handles window game loop
Post by: Elanif 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
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();
 

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;
        }
}
 

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.