Skip to content

Commit

Permalink
Rewrite sf::Event API to improve type safety
Browse files Browse the repository at this point in the history
This new API is built on top of std::variant. This allows us to
store many different event types in a space-efficient way and access
the active event type in a type-safe manner that eliminates the
categories of UB that are possible with unions.

Co-authored-by: kimci86 <kimci86@hotmail.fr>
  • Loading branch information
ChrisThrasher and kimci86 committed Mar 4, 2024
1 parent d7fb1bf commit bdeaae0
Show file tree
Hide file tree
Showing 43 changed files with 1,042 additions and 723 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ body:
{
for (sf::Event event; window.pollEvent(event);)
{
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();
}
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ body:
{
for (sf::Event event; window.pollEvent(event);)
{
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();
}
Expand Down
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ int main()
{
for (sf::Event event; window.pollEvent(event);)
{
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();
}

Expand Down
2 changes: 1 addition & 1 deletion doc/mainpage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
/// for (sf::Event event; window.pollEvent(event);)
/// {
/// // Close window: exit
/// if (event.type == sf::Event::Closed)
/// if (event.is<sf::Event::Closed>())
/// window.close();
/// }
///
Expand Down
34 changes: 20 additions & 14 deletions examples/android/app/src/main/jni/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,44 +115,50 @@ int main(int argc, char* argv[])
{
for (sf::Event event; active ? window.pollEvent(event) : window.waitEvent(event);)
{
switch (event.type)
switch (event.getType())
{
case sf::Event::Closed:
case sf::Event::Type::Closed:
window.close();
break;
case sf::Event::KeyPressed:
if (event.key.code == sf::Keyboard::Key::Escape)
case sf::Event::Type::KeyPressed:
if (event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape)
window.close();
break;
case sf::Event::Resized:
view.setSize(sf::Vector2f(event.size.width, event.size.height));
view.setCenter(sf::Vector2f(event.size.width, event.size.height) / 2.f);
case sf::Event::Type::Resized:
{
const auto size = sf::Vector2f(event.get<sf::Event::Resized>().size);
view.setSize(size);
view.setCenter(size / 2.f);
window.setView(view);
break;
case sf::Event::LostFocus:
}
case sf::Event::Type::FocusLost:
background = sf::Color::Black;
break;
case sf::Event::GainedFocus:
case sf::Event::Type::FocusGained:
background = sf::Color::White;
break;

// On Android MouseLeft/MouseEntered are (for now) triggered,
// whenever the app loses or gains focus.
case sf::Event::MouseLeft:
case sf::Event::Type::MouseLeft:
active = false;
break;
case sf::Event::MouseEntered:
case sf::Event::Type::MouseEntered:
active = true;
break;
case sf::Event::TouchBegan:
if (event.touch.finger == 0)
case sf::Event::Type::TouchBegan:
{
const auto& touchBegan = event.get<sf::Event::TouchBegan>();
if (touchBegan.finger == 0)
{
image.setPosition({static_cast<float>(event.touch.x), static_cast<float>(event.touch.y)});
image.setPosition(sf::Vector2f(touchBegan.position));
#if defined(USE_JNI)
vibrate(sf::milliseconds(10));
#endif
}
break;
}
default:
break;
}
Expand Down
8 changes: 4 additions & 4 deletions examples/island/Island.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,17 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape)))
if (event.is<sf::Event::Closed>() ||
(event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape))
{
window.close();
break;
}

// Arrow key pressed:
if (prerequisitesSupported && (event.type == sf::Event::KeyPressed))
if (prerequisitesSupported && event.is<sf::Event::KeyPressed>())
{
switch (event.key.code)
switch (event.get<sf::Event::KeyPressed>().code)
{
case sf::Keyboard::Key::Enter:
generateTerrain(terrainStagingBuffer.data());
Expand Down
26 changes: 20 additions & 6 deletions examples/joystick/Joystick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,33 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape)))
if (event.is<sf::Event::Closed>() ||
(event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape))
{
window.close();
break;
}
else if ((event.type == sf::Event::JoystickButtonPressed) || (event.type == sf::Event::JoystickButtonReleased) ||
(event.type == sf::Event::JoystickMoved) || (event.type == sf::Event::JoystickConnected))
else if (const auto* joystickButtonPressed = event.getIf<sf::Event::JoystickButtonPressed>())
{
// Update displayed joystick values
updateValues(event.joystickConnect.joystickId);
updateValues(joystickButtonPressed->joystickId);
}
else if (event.type == sf::Event::JoystickDisconnected)
else if (const auto* joystickButtonReleased = event.getIf<sf::Event::JoystickButtonReleased>())
{
// Update displayed joystick values
updateValues(joystickButtonReleased->joystickId);
}
else if (const auto* joystickMoved = event.getIf<sf::Event::JoystickMoved>())
{
// Update displayed joystick values
updateValues(joystickMoved->joystickId);
}
else if (const auto* joystickConnected = event.getIf<sf::Event::JoystickConnected>())
{
// Update displayed joystick values
updateValues(joystickConnected->joystickId);
}
else if (event.is<sf::Event::JoystickDisconnected>())
{
// Reset displayed joystick values to empty
for (auto& [label, joystickObject] : texts)
Expand Down
18 changes: 11 additions & 7 deletions examples/opengl/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,21 +211,23 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Close window: exit
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
{
exit = true;
window.close();
}

// Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape))
if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>();
keyPressed && keyPressed->code == sf::Keyboard::Key::Escape)
{
exit = true;
window.close();
}

// Return key: toggle mipmapping
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Enter))
if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>();
keyPressed && keyPressed->code == sf::Keyboard::Key::Enter)
{
if (mipmapEnabled)
{
Expand All @@ -242,14 +244,15 @@ int main()
}

// Space key: toggle sRGB conversion
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Space))
if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>();
keyPressed && keyPressed->code == sf::Keyboard::Key::Space)
{
sRgb = !sRgb;
window.close();
}

// Adjust the viewport when the window is resized
if (event.type == sf::Event::Resized)
if (const auto* resized = event.getIf<sf::Event::Resized>())
{
const sf::Vector2u textureSize = backgroundTexture.getSize();

Expand All @@ -260,10 +263,11 @@ int main()
return EXIT_FAILURE;
}

glViewport(0, 0, static_cast<GLsizei>(event.size.width), static_cast<GLsizei>(event.size.height));
const auto [width, height] = resized->size;
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const GLfloat newRatio = static_cast<float>(event.size.width) / static_cast<float>(event.size.height);
const GLfloat newRatio = static_cast<float>(width) / static_cast<float>(height);
#ifdef SFML_OPENGL_ES
glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f);
#else
Expand Down
6 changes: 3 additions & 3 deletions examples/shader/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,12 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Close window: exit
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();

if (event.type == sf::Event::KeyPressed)
if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>())
{
switch (event.key.code)
switch (keyPressed->code)
{
// Escape key: exit
case sf::Keyboard::Key::Escape:
Expand Down
2 changes: 1 addition & 1 deletion examples/stencil/Stencil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Window closed: exit
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
{
window.close();
break;
Expand Down
10 changes: 5 additions & 5 deletions examples/tennis/Tennis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape)))
if (event.is<sf::Event::Closed>() ||
(event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape))
{
window.close();
break;
}

// Space key pressed: play
if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Space)) ||
(event.type == sf::Event::TouchBegan))
if ((event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Space) ||
event.is<sf::Event::TouchBegan>())
{
if (!isPlaying)
{
Expand All @@ -150,7 +150,7 @@ int main()
}

// Window size changed, adjust view appropriately
if (event.type == sf::Event::Resized)
if (event.is<sf::Event::Resized>())
{
sf::View view;
view.setSize({gameWidth, gameHeight});
Expand Down
6 changes: 3 additions & 3 deletions examples/vulkan/Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2545,15 +2545,15 @@ class VulkanExample
for (sf::Event event; window.pollEvent(event);)
{
// Close window: exit
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();

// Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape))
if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape)
window.close();

// Re-create the swapchain when the window is resized
if (event.type == sf::Event::Resized)
if (event.is<sf::Event::Resized>())
swapchainOutOfDate = true;
}

Expand Down
11 changes: 6 additions & 5 deletions examples/window/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,21 @@ int main()
for (sf::Event event; window.pollEvent(event);)
{
// Close window: exit
if (event.type == sf::Event::Closed)
if (event.is<sf::Event::Closed>())
window.close();

// Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape))
if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Key::Escape)
window.close();

// Resize event: adjust the viewport
if (event.type == sf::Event::Resized)
if (const auto* resized = event.getIf<sf::Event::Resized>())
{
glViewport(0, 0, static_cast<GLsizei>(event.size.width), static_cast<GLsizei>(event.size.height));
const auto [width, height] = resized->size;
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const GLfloat newRatio = static_cast<float>(event.size.width) / static_cast<float>(event.size.height);
const GLfloat newRatio = static_cast<float>(width) / static_cast<float>(height);
#ifdef SFML_OPENGL_ES
glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f);
#else
Expand Down
2 changes: 1 addition & 1 deletion include/SFML/Graphics/RenderWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget
/// for (sf::Event event; window.pollEvent(event);)
/// {
/// // Request for closing the window
/// if (event.type == sf::Event::Closed)
/// if (event.is<sf::Event::Closed>())
/// window.close();
/// }
///
Expand Down
9 changes: 5 additions & 4 deletions include/SFML/Window/Clipboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,17 @@ SFML_WINDOW_API void setString(const String& text);
/// // or use it in the event loop
/// for (sf::Event event; window.pollEvent(event);)
/// {
/// if(event.type == sf::Event::Closed)
/// if(event.is<sf::Event::Closed>())
/// window.close();
/// if(event.type == sf::Event::KeyPressed)
/// if(event.is<sf::Event::KeyPressed>())
/// {
/// const auto& keyPressed = event.get<sf::Event::KeyPressed>();
/// // Using Ctrl + V to paste a string into SFML
/// if(event.key.control && event.key.code == sf::Keyboard::Key::V)
/// if(keyPressed.control && keyPressed.code == sf::Keyboard::Key::V)
/// string = sf::Clipboard::getString();
///
/// // Using Ctrl + C to copy a string out of SFML
/// if(event.key.control && event.key.code == sf::Keyboard::Key::C)
/// if(keyPressed.control && keyPressed.code == sf::Keyboard::Key::C)
/// sf::Clipboard::setString("Hello World!");
/// }
/// }
Expand Down

0 comments on commit bdeaae0

Please sign in to comment.