Window Events

Learn how to handle window events with our own callbacks

Source Code

The SFML Window

The image below shows an SFML window. Look at that window, it is doing nothing, only displaying a black screen !? Well, actually not ! This boring window doing nothing is actually spying on you, every time you move your mouse or click a button (keyboard, mouse, or joystick) the window knows it.

The code below is extracted from the SFML source code here. It shows the moment SFML captures your mouse right-click. In reality, it’s your Operating System (Windows in our case) that spies on you and listens to all your inputs. SFML just retrieves the information from the OS and creates an sf::Event that it “Pushes” on its Event Queue. This happens continuously so your SFML window knows everything you’re doing at any time.

void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        // Mouse right button down event
        case WM_RBUTTONDOWN:
        {
            Event event;
            event.type               = Event::MouseButtonPressed;
            event.mouseButton.button = Mouse::Right;
            event.mouseButton.x      = static_cast(LOWORD(lParam));
            event.mouseButton.y      = static_cast(HIWORD(lParam));
            //Add New Event on the Event Queue
            pushEvent(event);
            break;
        }
    }
}

SFML Window Events

It’s the SFML window that captures all your Events (Keyboard, Mouse, Joystick), but the Window by itself also emits some events. Four events are emitted directly from the window

  • sf::Event::Closed : Emitted when the window receives a request for closing (when you click on the close button on the upper-left or when you do ALT + F4)
  • sf::Event::Resized : Emitted when the window get resized (for example by grabbing and dragging its borders with the mouse)
  • sf::Event::GainedFocus : Emitted when the window gains the focus
  • sf::Event::LostFocus : Emitted when the window loses the focus
The code below shows how to handle those four types of Events. The events Resized queries two information, the new width and the new height of the window after the resize. The events Closed, GainedFocus and LostFocus do not query any information.
void handleEvent(const sf::Event& event)
{
    //Closed Event
    if(event.type == sf::Event::Closed)
    {
        nero_log("closing window");
        //getRenderWindow().close();
    }
    //Resized Event
    else if(event.type == sf::Event::Resized)
    {
        unsigned int new_width  = event.size.width;
        unsigned int new_height = event.size.height;
        nero_log(_se(new_width));
        nero_log(_se(new_height));
    }
    //GainedFocus Event
    else  if(event.type == sf::Event::GainedFocus)
    {
       nero_log("window just gained focus");
    }
    //LostFocus Event
    else if(event.type == sf::Event::LostFocus)
    {
       nero_log("window just lost focus");
    }
}

Window Events Callbacks

Now that you know how to use those 4 events, let’s improve our code by implementing our own callbacks.  Instead of handling the Window Events inside the Event Loop, we’ll use the three callbacks below

  • onWindowClosed()
  • onWindowResized(sf::Vector2u)
  • onWindowFocusChanged(bool)
void onWindowClosed()
{
    //do something
        //save the game
        //show a pop-up to the user asking if he/she really want to close
        //Etc.
        //close the window
}
void onWindowResized(const sf::Vector2u& size)
{
    //do something
        //update the scene resolution
        //update your OpenGL view
        //Etc.
}
void onWindowFocusChanged(const bool& gainedFocus)
{
    //do something
        //pause the game if gainedFocus = false
        //resume the game if gainedFocus = true
        //Etc.
}

The code below shows our new improved handleEvent(event) method, pretty isn’t it !?

void handleEvent(const sf::Event& event)
{
    if(event.type == sf::Event::Closed)
    {
        onWindowClosed();
    }
    else if(event.type == sf::Event::Resized)
    {
        onWindowResized(sf::Vector2u(event.size.width, event.size.height));
    }
    else  if(event.type == sf::Event::GainedFocus)
    {
        onWindowFocusChanged(true);
    }
    else if(event.type == sf::Event::LostFocus)
    {
        onWindowFocusChanged(false);
    }
}