Rewrite sf::Event API to improve type safety

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>
This commit is contained in:
Chris Thrasher 2023-11-03 21:47:14 -06:00
parent 39ba64cfc6
commit 5735fd09d9
No known key found for this signature in database
GPG Key ID: 56FB686C9DFC8E2C
37 changed files with 971 additions and 679 deletions

View File

@ -59,7 +59,7 @@ body:
{ {
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); window.close();
} }

View File

@ -56,7 +56,7 @@ body:
{ {
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); window.close();
} }

View File

@ -41,7 +41,7 @@ int main()
{ {
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); window.close();
} }

View File

@ -47,7 +47,7 @@
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// // Close window: exit /// // Close window: exit
/// if (event.type == sf::Event::Closed) /// if (event.is<sf::Event::Closed>())
/// window.close(); /// window.close();
/// } /// }
/// ///

View File

@ -115,44 +115,50 @@ int main(int argc, char* argv[])
{ {
for (sf::Event event; active ? window.pollEvent(event) : window.waitEvent(event);) 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(); window.close();
break; break;
case sf::Event::KeyPressed: case sf::Event::Type::KeyPressed:
if (event.key.code == sf::Keyboard::Escape) if (event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
window.close(); window.close();
break; break;
case sf::Event::Resized: case sf::Event::Type::Resized:
view.setSize(sf::Vector2f(event.size.width, event.size.height)); {
view.setCenter(sf::Vector2f(event.size.width, event.size.height) / 2.f); const auto size = sf::Vector2f(event.get<sf::Event::Resized>().size);
view.setSize(size);
view.setCenter(size / 2.f);
window.setView(view); window.setView(view);
break; break;
case sf::Event::LostFocus: }
case sf::Event::Type::LostFocus:
background = sf::Color::Black; background = sf::Color::Black;
break; break;
case sf::Event::GainedFocus: case sf::Event::Type::GainedFocus:
background = sf::Color::White; background = sf::Color::White;
break; break;
// On Android MouseLeft/MouseEntered are (for now) triggered, // On Android MouseLeft/MouseEntered are (for now) triggered,
// whenever the app loses or gains focus. // whenever the app loses or gains focus.
case sf::Event::MouseLeft: case sf::Event::Type::MouseLeft:
active = false; active = false;
break; break;
case sf::Event::MouseEntered: case sf::Event::Type::MouseEntered:
active = true; active = true;
break; break;
case sf::Event::TouchBegan: case sf::Event::Type::TouchBegan:
if (event.touch.finger == 0) {
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) #if defined(USE_JNI)
vibrate(sf::milliseconds(10)); vibrate(sf::milliseconds(10));
#endif #endif
} }
break; break;
}
} }
} }

View File

@ -182,17 +182,17 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Window closed or escape key pressed: exit // Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) || if (event.is<sf::Event::Closed>() ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape))
{ {
window.close(); window.close();
break; break;
} }
// Arrow key pressed: // 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::Enter: case sf::Keyboard::Enter:
generateTerrain(terrainStagingBuffer.data()); generateTerrain(terrainStagingBuffer.data());

View File

@ -162,19 +162,33 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Window closed or escape key pressed: exit // Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) || if (event.is<sf::Event::Closed>() ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape))
{ {
window.close(); window.close();
break; break;
} }
else if ((event.type == sf::Event::JoystickButtonPressed) || (event.type == sf::Event::JoystickButtonReleased) || else if (const auto* joystickButtonPressed = event.getIf<sf::Event::JoystickButtonPressed>())
(event.type == sf::Event::JoystickMoved) || (event.type == sf::Event::JoystickConnected))
{ {
// Update displayed joystick values // 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 // Reset displayed joystick values to empty
for (auto& [label, joystickObject] : texts) for (auto& [label, joystickObject] : texts)

View File

@ -207,21 +207,21 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
{ {
exit = true; exit = true;
window.close(); window.close();
} }
// Escape key: exit // Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
{ {
exit = true; exit = true;
window.close(); window.close();
} }
// Return key: toggle mipmapping // Return key: toggle mipmapping
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Enter)) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Enter)
{ {
if (mipmapEnabled) if (mipmapEnabled)
{ {
@ -238,14 +238,14 @@ int main()
} }
// Space key: toggle sRGB conversion // Space key: toggle sRGB conversion
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Space)
{ {
sRgb = !sRgb; sRgb = !sRgb;
window.close(); window.close();
} }
// Adjust the viewport when the window is resized // 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(); const sf::Vector2u textureSize = backgroundTexture.getSize();
@ -256,10 +256,11 @@ int main()
return EXIT_FAILURE; 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); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); 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 #ifdef SFML_OPENGL_ES
glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f); glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f);
#else #else

View File

@ -393,12 +393,12 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); 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 // Escape key: exit
case sf::Keyboard::Escape: case sf::Keyboard::Escape:

View File

@ -114,16 +114,16 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Window closed or escape key pressed: exit // Window closed or escape key pressed: exit
if ((event.type == sf::Event::Closed) || if (event.is<sf::Event::Closed>() ||
((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape))
{ {
window.close(); window.close();
break; break;
} }
// Space key pressed: play // Space key pressed: play
if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) || if ((event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Space) ||
(event.type == sf::Event::TouchBegan)) event.is<sf::Event::TouchBegan>())
{ {
if (!isPlaying) if (!isPlaying)
{ {
@ -146,7 +146,7 @@ int main()
} }
// Window size changed, adjust view appropriately // Window size changed, adjust view appropriately
if (event.type == sf::Event::Resized) if (event.is<sf::Event::Resized>())
{ {
sf::View view; sf::View view;
view.setSize({gameWidth, gameHeight}); view.setSize({gameWidth, gameHeight});

View File

@ -2544,15 +2544,15 @@ public:
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); window.close();
// Escape key: exit // Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
window.close(); window.close();
// Re-create the swapchain when the window is resized // Re-create the swapchain when the window is resized
if (event.type == sf::Event::Resized) if (event.is<sf::Event::Resized>())
swapchainOutOfDate = true; swapchainOutOfDate = true;
} }

View File

@ -144,20 +144,21 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
window.close(); window.close();
// Escape key: exit // Escape key: exit
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
window.close(); window.close();
// Resize event: adjust the viewport // 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); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); 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 #ifdef SFML_OPENGL_ES
glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f); glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f);
#else #else

View File

@ -218,7 +218,7 @@ private:
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// // Request for closing the window /// // Request for closing the window
/// if (event.type == sf::Event::Closed) /// if (event.is<sf::Event::Closed>())
/// window.close(); /// window.close();
/// } /// }
/// ///

View File

@ -93,16 +93,17 @@ SFML_WINDOW_API void setString(const String& text);
/// // or use it in the event loop /// // or use it in the event loop
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// if(event.type == sf::Event::Closed) /// if(event.is<sf::Event::Closed>())
/// window.close(); /// 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 /// // Using Ctrl + V to paste a string into SFML
/// if(event.key.control && event.key.code == sf::Keyboard::V) /// if(keyPressed.control && keyPressed.code == sf::Keyboard::V)
/// string = sf::Clipboard::getString(); /// string = sf::Clipboard::getString();
/// ///
/// // Using Ctrl + C to copy a string out of SFML /// // Using Ctrl + C to copy a string out of SFML
/// if(event.key.control && event.key.code == sf::Keyboard::C) /// if(keyPressed.control && keyPressed.code == sf::Keyboard::C)
/// sf::Clipboard::setString("Hello World!"); /// sf::Clipboard::setString("Hello World!");
/// } /// }
/// } /// }

View File

@ -34,8 +34,10 @@
#include <SFML/Window/Mouse.hpp> #include <SFML/Window/Mouse.hpp>
#include <SFML/Window/Sensor.hpp> #include <SFML/Window/Sensor.hpp>
#include <SFML/System/Vector2.hpp>
#include <variant>
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
namespace sf namespace sf
{ {
@ -43,186 +45,375 @@ namespace sf
/// \brief Defines a system event and its parameters /// \brief Defines a system event and its parameters
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct Event class SFML_WINDOW_API Event
{ {
public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Size events parameters (Resized) /// \brief Empty event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct SizeEvent struct Empty
{ {
unsigned int width; //!< New width, in pixels
unsigned int height; //!< New height, in pixels
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Keyboard event parameters (KeyPressed, KeyReleased) /// \brief Closed event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct KeyEvent struct Closed
{ {
Keyboard::Key code; //!< Code of the key that has been pressed
Keyboard::Scancode scancode; //!< Physical code of the key that has been pressed
bool alt; //!< Is the Alt key pressed?
bool control; //!< Is the Control key pressed?
bool shift; //!< Is the Shift key pressed?
bool system; //!< Is the System key pressed?
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Text event parameters (TextEntered) /// \brief Resized event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct TextEvent struct Resized
{ {
std::uint32_t unicode; //!< UTF-32 Unicode value of the character Vector2u size; //!< New size, in pixels
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse move event parameters (MouseMoved) /// \brief Lost focus event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct MouseMoveEvent struct LostFocus
{ {
int x; //!< X position of the mouse pointer, relative to the left of the owner window
int y; //!< Y position of the mouse pointer, relative to the top of the owner window
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse buttons events parameters /// \brief Gained focus event
/// (MouseButtonPressed, MouseButtonReleased)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct MouseButtonEvent struct GainedFocus
{ {
Mouse::Button button; //!< Code of the button that has been pressed
int x; //!< X position of the mouse pointer, relative to the left of the owner window
int y; //!< Y position of the mouse pointer, relative to the top of the owner window
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Mouse wheel events parameters (MouseWheelScrolled) /// \brief Text event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct MouseWheelScrollEvent struct TextEntered
{ {
Mouse::Wheel wheel; //!< Which wheel (for mice with multiple ones) std::uint32_t unicode{}; //!< UTF-32 Unicode value of the character
float delta; //!< Wheel offset (positive is up/left, negative is down/right). High-precision mice may use non-integral offsets.
int x; //!< X position of the mouse pointer, relative to the left of the owner window
int y; //!< Y position of the mouse pointer, relative to the top of the owner window
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Joystick connection events parameters /// \brief KeyChanged events
/// (JoystickConnected, JoystickDisconnected)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct JoystickConnectEvent struct KeyChanged
{
Keyboard::Key code{}; //!< Code of the key
Keyboard::Scancode scancode{}; //!< Physical code of the key
bool alt{}; //!< Is the Alt key pressed?
bool control{}; //!< Is the Control key pressed?
bool shift{}; //!< Is the Shift key pressed?
bool system{}; //!< Is the System key pressed?
};
struct KeyPressed : KeyChanged
{
};
struct KeyReleased : KeyChanged
{ {
unsigned int joystickId; //!< Index of the joystick (in range [0 .. Joystick::Count - 1])
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Joystick axis move event parameters (JoystickMoved) /// \brief Mouse wheel scrolled event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct JoystickMoveEvent struct MouseWheelScrolled
{ {
unsigned int joystickId; //!< Index of the joystick (in range [0 .. Joystick::Count - 1]) Mouse::Wheel wheel{}; //!< Which wheel (for mice with multiple ones)
Joystick::Axis axis; //!< Axis on which the joystick moved float delta{}; //!< Wheel offset (positive is up/left, negative is down/right). High-precision mice may use non-integral offsets.
float position; //!< New position on the axis (in range [-100 .. 100]) Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Joystick buttons events parameters /// \brief Mouse button changed events
/// (JoystickButtonPressed, JoystickButtonReleased)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct JoystickButtonEvent struct MouseButtonChanged
{
Mouse::Button button{}; //!< Code of the button that has been pressed
Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window
};
struct MouseButtonPressed : MouseButtonChanged
{
};
struct MouseButtonReleased : MouseButtonChanged
{ {
unsigned int joystickId; //!< Index of the joystick (in range [0 .. Joystick::Count - 1])
unsigned int button; //!< Index of the button that has been pressed (in range [0 .. Joystick::ButtonCount - 1])
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Touch events parameters (TouchBegan, TouchMoved, TouchEnded) /// \brief Mouse move event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct TouchEvent struct MouseMoved
{ {
unsigned int finger; //!< Index of the finger in case of multi-touch events Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window
int x; //!< X position of the touch, relative to the left of the owner window
int y; //!< Y position of the touch, relative to the top of the owner window
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Sensor event parameters (SensorChanged) /// \brief Mouse entered event
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct SensorEvent struct MouseEntered
{ {
Sensor::Type type; //!< Type of the sensor };
float x; //!< Current value of the sensor on X axis
float y; //!< Current value of the sensor on Y axis ////////////////////////////////////////////////////////////
float z; //!< Current value of the sensor on Z axis /// \brief Mouse left event
///
////////////////////////////////////////////////////////////
struct MouseLeft
{
};
////////////////////////////////////////////////////////////
/// \brief Joystick button events
///
////////////////////////////////////////////////////////////
struct JoystickButtonChanged
{
unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1])
unsigned int button{}; //!< Index of the button that has been pressed (in range [0 .. Joystick::ButtonCount - 1])
};
struct JoystickButtonPressed : JoystickButtonChanged
{
};
struct JoystickButtonReleased : JoystickButtonChanged
{
};
////////////////////////////////////////////////////////////
/// \brief Joystick axis move event
///
////////////////////////////////////////////////////////////
struct JoystickMoved
{
unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1])
Joystick::Axis axis{}; //!< Axis on which the joystick moved
float position{}; //!< New position on the axis (in range [-100 .. 100])
};
////////////////////////////////////////////////////////////
/// \brief Joystick connection events
///
////////////////////////////////////////////////////////////
struct JoystickChanged
{
unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1])
};
struct JoystickConnected : JoystickChanged
{
};
struct JoystickDisconnected : JoystickChanged
{
};
////////////////////////////////////////////////////////////
/// \brief Touch events
///
////////////////////////////////////////////////////////////
struct TouchChanged
{
unsigned int finger{}; //!< Index of the finger in case of multi-touch events
Vector2i position; //!< Position of the touch, relative to the top left of the owner window
};
struct TouchBegan : TouchChanged
{
};
struct TouchMoved : TouchChanged
{
};
struct TouchEnded : TouchChanged
{
};
////////////////////////////////////////////////////////////
/// \brief Sensor event
///
////////////////////////////////////////////////////////////
struct SensorChanged
{
Sensor::Type type{}; //!< Type of the sensor
Vector3f value; //!< Current value of the sensor on the X, Y, and Z axes
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Enumeration of the different types of events /// \brief Enumeration of the different types of events
/// ///
/// Each event type maps 1-to-1 to a specific structure of
/// the same name.
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
enum EventType enum class Type
{ {
Closed, //!< The window requested to be closed (no data) Empty, //!< Default type
Resized, //!< The window was resized (data in event.size) Closed, //!< The window requested to be closed
LostFocus, //!< The window lost the focus (no data) Resized, //!< The window was resized
GainedFocus, //!< The window gained the focus (no data) LostFocus, //!< The window lost the focus
TextEntered, //!< A character was entered (data in event.text) GainedFocus, //!< The window gained the focus
KeyPressed, //!< A key was pressed (data in event.key) TextEntered, //!< A character was entered
KeyReleased, //!< A key was released (data in event.key) KeyPressed, //!< A key was pressed
MouseWheelScrolled, //!< The mouse wheel was scrolled (data in event.mouseWheelScroll) KeyReleased, //!< A key was released
MouseButtonPressed, //!< A mouse button was pressed (data in event.mouseButton) MouseWheelScrolled, //!< The mouse wheel was scrolled
MouseButtonReleased, //!< A mouse button was released (data in event.mouseButton) MouseButtonPressed, //!< A mouse button was pressed
MouseMoved, //!< The mouse cursor moved (data in event.mouseMove) MouseButtonReleased, //!< A mouse button was released
MouseEntered, //!< The mouse cursor entered the area of the window (no data) MouseMoved, //!< The mouse cursor moved
MouseLeft, //!< The mouse cursor left the area of the window (no data) MouseEntered, //!< The mouse cursor entered the area of the window
JoystickButtonPressed, //!< A joystick button was pressed (data in event.joystickButton) MouseLeft, //!< The mouse cursor left the area of the window
JoystickButtonReleased, //!< A joystick button was released (data in event.joystickButton) JoystickButtonPressed, //!< A joystick button was pressed
JoystickMoved, //!< The joystick moved along an axis (data in event.joystickMove) JoystickButtonReleased, //!< A joystick button was released
JoystickConnected, //!< A joystick was connected (data in event.joystickConnect) JoystickMoved, //!< The joystick moved along an axis
JoystickDisconnected, //!< A joystick was disconnected (data in event.joystickConnect) JoystickConnected, //!< A joystick was connected
TouchBegan, //!< A touch event began (data in event.touch) JoystickDisconnected, //!< A joystick was disconnected
TouchMoved, //!< A touch moved (data in event.touch) TouchBegan, //!< A touch event began
TouchEnded, //!< A touch event ended (data in event.touch) TouchMoved, //!< A touch moved
SensorChanged, //!< A sensor value changed (data in event.sensor) TouchEnded, //!< A touch event ended
SensorChanged, //!< A sensor value changed
Count //!< Keep last -- the total number of event types
}; };
private:
using VariantType = std::variant<
Empty,
Closed,
Resized,
LostFocus,
GainedFocus,
TextEntered,
KeyPressed,
KeyReleased,
MouseWheelScrolled,
MouseButtonPressed,
MouseButtonReleased,
MouseMoved,
MouseEntered,
MouseLeft,
JoystickButtonPressed,
JoystickButtonReleased,
JoystickMoved,
JoystickConnected,
JoystickDisconnected,
TouchBegan,
TouchMoved,
TouchEnded,
SensorChanged>;
template <typename T, typename... Ts>
static constexpr bool isInParameterPack(const std::variant<Ts...>&)
{
return (std::is_same_v<T, Ts> || ...);
}
template <typename T>
static constexpr bool isEventType = isInParameterPack<T>(VariantType());
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Sets the event to Type::Empty
///
////////////////////////////////////////////////////////////
Event() = default;
////////////////////////////////////////////////////////////
/// \brief Construct from a given sf::Event subtype
///
/// \param t Event subtype
///
////////////////////////////////////////////////////////////
template <typename T>
Event(const T& t);
////////////////////////////////////////////////////////////
/// \brief Get current event type
///
/// \return Current event type
///
////////////////////////////////////////////////////////////
[[nodiscard]] Type getType() const;
////////////////////////////////////////////////////////////
/// \brief Check current event type
///
/// \return True if template parameter is current event type
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] bool is() const;
////////////////////////////////////////////////////////////
/// \brief Get particular event type
///
/// Throws std::bad_variant_access if event type does not
/// match the current event type.
///
/// \return Reference to current event type
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] const T& get() const;
////////////////////////////////////////////////////////////
/// \brief Get particular event type
///
/// \return Address of current event type, otherwise nullptr
///
////////////////////////////////////////////////////////////
template <typename T>
[[nodiscard]] const T* getIf() const;
private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
EventType type{}; //!< Type of the event VariantType m_data; //!< Event data
union
{
SizeEvent size; //!< Size event parameters (Event::Resized)
KeyEvent key; //!< Key event parameters (Event::KeyPressed, Event::KeyReleased)
TextEvent text; //!< Text event parameters (Event::TextEntered)
MouseMoveEvent mouseMove; //!< Mouse move event parameters (Event::MouseMoved)
MouseButtonEvent mouseButton; //!< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased)
MouseWheelScrollEvent mouseWheelScroll; //!< Mouse wheel event parameters (Event::MouseWheelScrolled)
JoystickMoveEvent joystickMove; //!< Joystick move event parameters (Event::JoystickMoved)
JoystickButtonEvent joystickButton; //!< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased)
JoystickConnectEvent joystickConnect; //!< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected)
TouchEvent touch; //!< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded)
SensorEvent sensor; //!< Sensor event parameters (Event::SensorChanged)
};
}; };
} // namespace sf ////////////////////////////////////////////////////////////
template <typename T>
Event::Event(const T& t)
{
if constexpr (isEventType<T>)
m_data = t;
else
static_assert(isEventType<T>, "T must be a subtype of sf::Event");
}
// NOLINTEND(cppcoreguidelines-pro-type-member-init) ////////////////////////////////////////////////////////////
template <typename T>
bool Event::is() const
{
if constexpr (isEventType<T>)
return std::holds_alternative<T>(m_data);
else
static_assert(isEventType<T>, "T must be a subtype of sf::Event");
}
////////////////////////////////////////////////////////////
template <typename T>
const T& Event::get() const
{
if constexpr (isEventType<T>)
return std::get<T>(m_data);
else
static_assert(isEventType<T>, "T must be a subtype of sf::Event");
}
////////////////////////////////////////////////////////////
template <typename T>
const T* Event::getIf() const
{
if constexpr (isEventType<T>)
return std::get_if<T>(&m_data);
else
static_assert(isEventType<T>, "T must be a subtype of sf::Event");
}
} // namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -235,30 +426,69 @@ struct Event
/// ///
/// A sf::Event instance contains the type of the event /// A sf::Event instance contains the type of the event
/// (mouse moved, key pressed, window closed, ...) as well /// (mouse moved, key pressed, window closed, ...) as well
/// as the details about this particular event. Please note that /// as the details about this particular event. Each event
/// the event parameters are defined in a union, which means that /// corresponds to a different struct which contains the data
/// only the member matching the type of the event will be properly /// required to process that event.
/// filled; all other members will have undefined values and must not ///
/// be read if the type of the event doesn't match. For example, /// Various member functions are provided to inspect the current
/// if you received a KeyPressed event, then you must read the /// active event and access it's data. These functions give you
/// event.key member, all other members such as event.mouseMove /// multiple options for how you choose to process events.
/// or event.text will have undefined values. ///
/// sf::Event::getType returns an enumeration where each value
/// matches the name of the struct that holds the corresponding
/// data. sf::Event::get can be used to retrieve that particular
/// struct. This combination works well if you want to use a switch
/// statement to process events.
///
/// \code
/// for (sf::Event event; window.pollEvent(event);)
/// {
/// switch (event.getType())
/// {
/// // Request for closing the window
/// case sf::Event::Type::Closed:
/// window.close();
/// break;
///
/// // The escape key was pressed
/// case sf::Event::Type::KeyPressed:
/// if (event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
/// window.close();
/// break;
///
/// // The window was resized
/// case sf::Event::Type::Resized:
/// doSomethingWithTheNewSize(event.get<sf::Event::Resized>().size);
/// break;
///
/// // etc ...
/// }
/// }
/// \endcode
///
/// An alternative means of accessing the current active event is
/// to use sf::Event::getIf which returns the address of the event
/// struct if it's active or a nullptr otherwise. sf::Event::is is
/// used to check the active event type without actually reading any
/// of the corresponding event data. These are useful if you need
/// to check only a single possible active event or prefer to
/// process events in a series of if/else if blocks.
/// ///
/// Usage example:
/// \code /// \code
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// // Request for closing the window /// // Request for closing the window
/// if (event.type == sf::Event::Closed) /// if (event.is<sf::Event::Closed>())
/// window.close(); /// window.close();
/// ///
/// // The escape key was pressed /// // The escape key was pressed
/// if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) /// if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>())
/// window.close(); /// if (keyPressed->code == sf::Keyboard::Escape)
/// window.close();
/// ///
/// // The window was resized /// // The window was resized
/// if (event.type == sf::Event::Resized) /// if (const auto* resized = event.getIf<sf::Event::Resized>())
/// doSomethingWithTheNewSize(event.size.width, event.size.height); /// doSomethingWithTheNewSize(resized->size);
/// ///
/// // etc ... /// // etc ...
/// } /// }

View File

@ -44,7 +44,7 @@ namespace priv
class GlContext; class GlContext;
} }
struct Event; class Event;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window that serves as a target for OpenGL rendering /// \brief Window that serves as a target for OpenGL rendering
@ -338,7 +338,7 @@ private:
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// // Request for closing the window /// // Request for closing the window
/// if (event.type == sf::Event::Closed) /// if (event.is<sf::Event::Closed>())
/// window.close(); /// window.close();
/// } /// }
/// ///

View File

@ -50,7 +50,7 @@ namespace priv
class WindowImpl; class WindowImpl;
} }
struct Event; class Event;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window that serves as a base for other windows /// \brief Window that serves as a base for other windows
@ -535,7 +535,7 @@ private:
/// for (sf::Event event; window.pollEvent(event);) /// for (sf::Event event; window.pollEvent(event);)
/// { /// {
/// // Request for closing the window /// // Request for closing the window
/// if (event.type == sf::Event::Closed) /// if (event.is<sf::Event::Closed>())
/// window.close(); /// window.close();
/// } /// }
/// ///

View File

@ -268,10 +268,7 @@ static void onResume(ANativeActivity* activity)
goToFullscreenMode(activity); goToFullscreenMode(activity);
// Send an event to warn people the activity has been resumed // Send an event to warn people the activity has been resumed
sf::Event event; states->forwardEvent(sf::Event::MouseEntered{});
event.type = sf::Event::MouseEntered;
states->forwardEvent(event);
} }
@ -283,10 +280,7 @@ static void onPause(ANativeActivity* activity)
std::lock_guard lock(states->mutex); std::lock_guard lock(states->mutex);
// Send an event to warn people the activity has been paused // Send an event to warn people the activity has been paused
sf::Event event; states->forwardEvent(sf::Event::MouseLeft{});
event.type = sf::Event::MouseLeft;
states->forwardEvent(event);
} }
@ -309,12 +303,7 @@ static void onDestroy(ANativeActivity* activity)
// If the main thread hasn't yet finished, send the event and wait for // If the main thread hasn't yet finished, send the event and wait for
// it to finish. // it to finish.
if (!states->mainOver) if (!states->mainOver)
{ states->forwardEvent(sf::Event::Closed{});
sf::Event event;
event.type = sf::Event::Closed;
states->forwardEvent(event);
}
} }
// Wait for the main thread to be terminated // Wait for the main thread to be terminated
@ -352,9 +341,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind
states->window = window; states->window = window;
// Notify SFML mechanism // Notify SFML mechanism
sf::Event event; states->forwardEvent(sf::Event::GainedFocus{});
event.type = sf::Event::GainedFocus;
states->forwardEvent(event);
// Wait for the event to be taken into account by SFML // Wait for the event to be taken into account by SFML
states->updated = false; states->updated = false;
@ -377,9 +364,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* /*
states->window = nullptr; states->window = nullptr;
// Notify SFML mechanism // Notify SFML mechanism
sf::Event event; states->forwardEvent(sf::Event::LostFocus{});
event.type = sf::Event::LostFocus;
states->forwardEvent(event);
// Wait for the event to be taken into account by SFML // Wait for the event to be taken into account by SFML
states->updated = false; states->updated = false;
@ -455,11 +440,8 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* /* rect
if (states->window != nullptr) if (states->window != nullptr)
{ {
// Send an event to warn people about the window move/resize // Send an event to warn people about the window move/resize
sf::Event event; const sf::Event::Resized event{
event.type = sf::Event::Resized; sf::Vector2u(sf::Vector2(ANativeWindow_getWidth(states->window), ANativeWindow_getHeight(states->window)))};
event.size.width = static_cast<unsigned int>(ANativeWindow_getWidth(states->window));
event.size.height = static_cast<unsigned int>(ANativeWindow_getHeight(states->window));
states->forwardEvent(event); states->forwardEvent(event);
} }
} }

View File

@ -233,14 +233,14 @@ void WindowImplAndroid::forwardEvent(const Event& event)
{ {
ActivityStates& states = getActivity(); ActivityStates& states = getActivity();
if (event.type == Event::GainedFocus) if (event.is<Event::GainedFocus>())
{ {
WindowImplAndroid::singleInstance->m_size = Vector2u( WindowImplAndroid::singleInstance->m_size = Vector2u(
Vector2i(ANativeWindow_getWidth(states.window), ANativeWindow_getHeight(states.window))); Vector2i(ANativeWindow_getWidth(states.window), ANativeWindow_getHeight(states.window)));
WindowImplAndroid::singleInstance->m_windowBeingCreated = true; WindowImplAndroid::singleInstance->m_windowBeingCreated = true;
WindowImplAndroid::singleInstance->m_hasFocus = true; WindowImplAndroid::singleInstance->m_hasFocus = true;
} }
else if (event.type == Event::LostFocus) else if (event.is<Event::LostFocus>())
{ {
WindowImplAndroid::singleInstance->m_windowBeingDestroyed = true; WindowImplAndroid::singleInstance->m_windowBeingDestroyed = true;
WindowImplAndroid::singleInstance->m_hasFocus = false; WindowImplAndroid::singleInstance->m_hasFocus = false;
@ -391,13 +391,10 @@ int WindowImplAndroid::processScrollEvent(AInputEvent* inputEvent, ActivityState
lJNIEnv->DeleteLocalRef(objectMotionEvent); lJNIEnv->DeleteLocalRef(objectMotionEvent);
// Create and send our mouse wheel event // Create and send our mouse wheel event
Event event; Event::MouseWheelScrolled event;
event.type = Event::MouseWheelScrolled; event.wheel = Mouse::VerticalWheel;
event.mouseWheelScroll.wheel = Mouse::VerticalWheel; event.delta = static_cast<float>(delta);
event.mouseWheelScroll.delta = static_cast<float>(delta); event.position = Vector2i(Vector2(AMotionEvent_getX(inputEvent, 0), AMotionEvent_getY(inputEvent, 0)));
event.mouseWheelScroll.x = static_cast<int>(AMotionEvent_getX(inputEvent, 0));
event.mouseWheelScroll.y = static_cast<int>(AMotionEvent_getY(inputEvent, 0));
forwardEvent(event); forwardEvent(event);
// Detach this thread from the JVM // Detach this thread from the JVM
@ -415,36 +412,28 @@ int WindowImplAndroid::processKeyEvent(AInputEvent* inputEvent, ActivityStates&
std::int32_t key = AKeyEvent_getKeyCode(inputEvent); std::int32_t key = AKeyEvent_getKeyCode(inputEvent);
std::int32_t metakey = AKeyEvent_getMetaState(inputEvent); std::int32_t metakey = AKeyEvent_getMetaState(inputEvent);
Event event; Event::KeyChanged keyChanged;
event.key.code = androidKeyToSF(key); keyChanged.code = androidKeyToSF(key);
event.key.alt = metakey & AMETA_ALT_ON; keyChanged.alt = metakey & AMETA_ALT_ON;
event.key.control = false; keyChanged.control = false;
event.key.shift = metakey & AMETA_SHIFT_ON; keyChanged.shift = metakey & AMETA_SHIFT_ON;
switch (action) switch (action)
{ {
case AKEY_EVENT_ACTION_DOWN: case AKEY_EVENT_ACTION_DOWN:
event.type = Event::KeyPressed; forwardEvent(Event::KeyPressed{keyChanged});
forwardEvent(event);
return 1; return 1;
case AKEY_EVENT_ACTION_UP: case AKEY_EVENT_ACTION_UP:
event.type = Event::KeyReleased; forwardEvent(Event::KeyReleased{keyChanged});
forwardEvent(event);
if (auto unicode = static_cast<std::uint32_t>(getUnicode(inputEvent))) if (auto unicode = static_cast<std::uint32_t>(getUnicode(inputEvent)))
{ forwardEvent(Event::TextEntered{static_cast<std::uint32_t>(unicode)});
event.type = Event::TextEntered;
event.text.unicode = static_cast<std::uint32_t>(unicode);
forwardEvent(event);
}
return 1; return 1;
case AKEY_EVENT_ACTION_MULTIPLE: case AKEY_EVENT_ACTION_MULTIPLE:
// Since complex inputs don't get separate key down/up events // Since complex inputs don't get separate key down/up events
// both have to be faked at once // both have to be faked at once
event.type = Event::KeyPressed; forwardEvent(Event::KeyPressed{keyChanged});
forwardEvent(event); forwardEvent(Event::KeyReleased{keyChanged});
event.type = Event::KeyReleased;
forwardEvent(event);
// This requires some special treatment, since this might represent // This requires some special treatment, since this might represent
// a repetition of key presses or a complete sequence // a repetition of key presses or a complete sequence
@ -456,8 +445,7 @@ int WindowImplAndroid::processKeyEvent(AInputEvent* inputEvent, ActivityStates&
} }
else if (auto unicode = static_cast<std::uint32_t>(getUnicode(inputEvent))) // This is a repeated sequence else if (auto unicode = static_cast<std::uint32_t>(getUnicode(inputEvent))) // This is a repeated sequence
{ {
event.type = Event::TextEntered; const Event event(Event::TextEntered{static_cast<std::uint32_t>(unicode)});
event.text.unicode = static_cast<std::uint32_t>(unicode);
std::int32_t repeats = AKeyEvent_getRepeatCount(inputEvent); std::int32_t repeats = AKeyEvent_getRepeatCount(inputEvent);
for (std::int32_t i = 0; i < repeats; ++i) for (std::int32_t i = 0; i < repeats; ++i)
@ -478,9 +466,9 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* inputEvent, ActivityState
Event event; Event event;
if (device == AINPUT_SOURCE_MOUSE) if (device == AINPUT_SOURCE_MOUSE)
event.type = Event::MouseMoved; event = Event::MouseMoved{};
else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN) else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN)
event.type = Event::TouchMoved; event = Event::TouchMoved{};
std::size_t pointerCount = AMotionEvent_getPointerCount(inputEvent); std::size_t pointerCount = AMotionEvent_getPointerCount(inputEvent);
@ -493,21 +481,20 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* inputEvent, ActivityState
if (device == AINPUT_SOURCE_MOUSE) if (device == AINPUT_SOURCE_MOUSE)
{ {
event.mouseMove.x = x; const Event::MouseMoved mouseMoved{{x, y}};
event.mouseMove.y = y; event = mouseMoved;
states.mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y); states.mousePosition = mouseMoved.position;
} }
else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN) else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN)
{ {
if (states.touchEvents[id].x == x && states.touchEvents[id].y == y) if (states.touchEvents[id].x == x && states.touchEvents[id].y == y)
continue; continue;
event.touch.finger = static_cast<unsigned int>(id); const Event::TouchMoved touchMoved{static_cast<unsigned int>(id), {x, y}};
event.touch.x = x; event = touchMoved;
event.touch.y = y;
states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y); states.touchEvents[id] = touchMoved.position;
} }
forwardEvent(event); forwardEvent(event);
@ -534,42 +521,33 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent,
{ {
if (device == AINPUT_SOURCE_MOUSE) if (device == AINPUT_SOURCE_MOUSE)
{ {
event.type = Event::MouseButtonPressed; event = Event::MouseButtonPressed{static_cast<Mouse::Button>(id), {x, y}};
event.mouseButton.button = static_cast<Mouse::Button>(id);
event.mouseButton.x = x;
event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount) if (id >= 0 && id < Mouse::ButtonCount)
states.isButtonPressed[id] = true; states.isButtonPressed[id] = true;
} }
else if (static_cast<unsigned int>(device) & AINPUT_SOURCE_TOUCHSCREEN) else if (static_cast<unsigned int>(device) & AINPUT_SOURCE_TOUCHSCREEN)
{ {
event.type = Event::TouchBegan; Event::TouchBegan touchBegan;
event.touch.finger = static_cast<unsigned int>(id); touchBegan.finger = static_cast<unsigned int>(id);
event.touch.x = x; touchBegan.position = {x, y};
event.touch.y = y; event = touchBegan;
states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y); states.touchEvents[id] = touchBegan.position;
} }
} }
else else
{ {
if (device == AINPUT_SOURCE_MOUSE) if (device == AINPUT_SOURCE_MOUSE)
{ {
event.type = Event::MouseButtonReleased; event = Event::MouseButtonReleased{static_cast<Mouse::Button>(id), {x, y}};
event.mouseButton.button = static_cast<Mouse::Button>(id);
event.mouseButton.x = x;
event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount) if (id >= 0 && id < Mouse::ButtonCount)
states.isButtonPressed[id] = false; states.isButtonPressed[id] = false;
} }
else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN) else if (static_cast<std::uint32_t>(device) & AINPUT_SOURCE_TOUCHSCREEN)
{ {
event.type = Event::TouchEnded; event = Event::TouchEnded{static_cast<unsigned int>(id), {x, y}};
event.touch.finger = static_cast<unsigned int>(id);
event.touch.x = x;
event.touch.y = y;
states.touchEvents.erase(id); states.touchEvents.erase(id);
} }

View File

@ -19,6 +19,7 @@ set(SRC
${INCROOT}/GlResource.hpp ${INCROOT}/GlResource.hpp
${INCROOT}/ContextSettings.hpp ${INCROOT}/ContextSettings.hpp
${INCROOT}/Event.hpp ${INCROOT}/Event.hpp
${SRCROOT}/Event.cpp
${SRCROOT}/InputImpl.hpp ${SRCROOT}/InputImpl.hpp
${INCROOT}/Joystick.hpp ${INCROOT}/Joystick.hpp
${SRCROOT}/Joystick.cpp ${SRCROOT}/Joystick.cpp

View File

@ -304,7 +304,7 @@ sf::Keyboard::Key toKey(int code)
} }
} }
void pushEvent(sf::Event& event) void pushEvent(const sf::Event& event)
{ {
if (eventQueue.size() >= maxQueue) if (eventQueue.size() >= maxQueue)
eventQueue.pop(); eventQueue.pop();
@ -323,31 +323,16 @@ void processSlots()
{ {
for (auto& slot : touchSlots) for (auto& slot : touchSlots)
{ {
sf::Event event;
event.touch.x = slot.pos.x;
event.touch.y = slot.pos.y;
if (slot.oldId == slot.id) if (slot.oldId == slot.id)
{ {
event.type = sf::Event::TouchMoved; pushEvent(sf::Event::TouchMoved{static_cast<unsigned int>(slot.id), slot.pos});
event.touch.finger = static_cast<unsigned int>(slot.id);
pushEvent(event);
} }
else else
{ {
if (slot.oldId != -1) if (slot.oldId != -1)
{ pushEvent(sf::Event::TouchEnded{static_cast<unsigned int>(slot.oldId), slot.pos});
event.type = sf::Event::TouchEnded;
event.touch.finger = static_cast<unsigned int>(slot.oldId);
pushEvent(event);
}
if (slot.id != -1) if (slot.id != -1)
{ pushEvent(sf::Event::TouchBegan{static_cast<unsigned int>(slot.id), slot.pos});
event.type = sf::Event::TouchBegan;
event.touch.finger = static_cast<unsigned int>(slot.id);
pushEvent(event);
}
slot.oldId = slot.id; slot.oldId = slot.id;
} }
@ -366,9 +351,8 @@ bool eventProcess(sf::Event& event)
static unsigned int doDeferredText = 0; static unsigned int doDeferredText = 0;
if (doDeferredText) if (doDeferredText)
{ {
event.type = sf::Event::TextEntered; event = sf::Event::TextEntered{doDeferredText};
event.text.unicode = doDeferredText; doDeferredText = 0;
doDeferredText = 0;
return true; return true;
} }
@ -387,10 +371,10 @@ bool eventProcess(sf::Event& event)
const sf::Mouse::Button mb = toMouseButton(inputEvent.code); const sf::Mouse::Button mb = toMouseButton(inputEvent.code);
if (mb != sf::Mouse::ButtonCount) if (mb != sf::Mouse::ButtonCount)
{ {
event.type = inputEvent.value ? sf::Event::MouseButtonPressed : sf::Event::MouseButtonReleased; if (inputEvent.value)
event.mouseButton.button = mb; event = sf::Event::MouseButtonPressed{mb, mousePos};
event.mouseButton.x = mousePos.x; else
event.mouseButton.y = mousePos.y; event = sf::Event::MouseButtonReleased{mb, mousePos};
mouseMap[mb] = inputEvent.value; mouseMap[mb] = inputEvent.value;
return true; return true;
@ -409,8 +393,7 @@ bool eventProcess(sf::Event& event)
// //
if (special) if (special)
{ {
event.type = sf::Event::TextEntered; event = sf::Event::TextEntered{special};
event.text.unicode = special;
return true; return true;
} }
} }
@ -418,13 +401,18 @@ bool eventProcess(sf::Event& event)
{ {
// key down and key up events // key down and key up events
// //
event.type = inputEvent.value ? sf::Event::KeyPressed : sf::Event::KeyReleased; sf::Event::KeyChanged keyChanged;
event.key.code = kb; keyChanged.code = kb;
event.key.scancode = sf::Keyboard::Scan::Unknown; // TODO: not implemented keyChanged.scancode = sf::Keyboard::Scan::Unknown; // TODO: not implemented
event.key.alt = altDown(); keyChanged.alt = altDown();
event.key.control = controlDown(); keyChanged.control = controlDown();
event.key.shift = shiftDown(); keyChanged.shift = shiftDown();
event.key.system = systemDown(); keyChanged.system = systemDown();
if (inputEvent.value)
event = sf::Event::KeyPressed{keyChanged};
else
event = sf::Event::KeyReleased{keyChanged};
keyMap[static_cast<std::size_t>(kb)] = inputEvent.value; keyMap[static_cast<std::size_t>(kb)] = inputEvent.value;
@ -451,18 +439,16 @@ bool eventProcess(sf::Event& event)
break; break;
case REL_WHEEL: case REL_WHEEL:
event.type = sf::Event::MouseWheelScrolled; sf::Event::MouseWheelScrolled mouseWheelScrolled;
event.mouseWheelScroll.delta = static_cast<float>(inputEvent.value); mouseWheelScrolled.delta = static_cast<float>(inputEvent.value);
event.mouseWheelScroll.x = mousePos.x; mouseWheelScrolled.position = mousePos;
event.mouseWheelScroll.y = mousePos.y; event = mouseWheelScrolled;
return true; return true;
} }
if (posChange) if (posChange)
{ {
event.type = sf::Event::MouseMoved; event = sf::Event::MouseMoved{mousePos};
event.mouseMove.x = mousePos.x;
event.mouseMove.y = mousePos.y;
return true; return true;
} }
} }
@ -547,8 +533,7 @@ bool eventProcess(sf::Event& event)
if (code > 0) if (code > 0)
{ {
// TODO: Proper unicode handling // TODO: Proper unicode handling
event.type = sf::Event::TextEntered; event = sf::Event::TextEntered{code};
event.text.unicode = code;
return true; return true;
} }

39
src/SFML/Window/Event.cpp Normal file
View File

@ -0,0 +1,39 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Event::Type Event::getType() const
{
return static_cast<Type>(m_data.index());
}
} // namespace sf

View File

@ -1720,9 +1720,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
err() << "Failed to grab mouse cursor" << std::endl; err() << "Failed to grab mouse cursor" << std::endl;
} }
Event event; pushEvent(Event::GainedFocus{});
event.type = Event::GainedFocus;
pushEvent(event);
// If the window has been previously marked urgent (notification) as a result of a focus request, undo that // If the window has been previously marked urgent (notification) as a result of a focus request, undo that
auto hints = X11Ptr<XWMHints>(XGetWMHints(m_display, m_window)); auto hints = X11Ptr<XWMHints>(XGetWMHints(m_display, m_window));
@ -1747,9 +1745,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
if (m_cursorGrabbed) if (m_cursorGrabbed)
XUngrabPointer(m_display, CurrentTime); XUngrabPointer(m_display, CurrentTime);
Event event; pushEvent(Event::LostFocus{});
event.type = Event::LostFocus;
pushEvent(event);
break; break;
} }
@ -1759,11 +1755,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// ConfigureNotify can be triggered for other reasons, check if the size has actually changed // ConfigureNotify can be triggered for other reasons, check if the size has actually changed
if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y)) if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y))
{ {
Event event; pushEvent(Event::Resized{Vector2u(Vector2(windowEvent.xconfigure.width, windowEvent.xconfigure.height))});
event.type = Event::Resized;
event.size.width = static_cast<unsigned int>(windowEvent.xconfigure.width);
event.size.height = static_cast<unsigned int>(windowEvent.xconfigure.height);
pushEvent(event);
m_previousSize.x = windowEvent.xconfigure.width; m_previousSize.x = windowEvent.xconfigure.width;
m_previousSize.y = windowEvent.xconfigure.height; m_previousSize.y = windowEvent.xconfigure.height;
@ -1789,9 +1781,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
(windowEvent.xclient.data.l[0]) == static_cast<long>(wmDeleteWindow)) (windowEvent.xclient.data.l[0]) == static_cast<long>(wmDeleteWindow))
{ {
// Handle the WM_DELETE_WINDOW message // Handle the WM_DELETE_WINDOW message
Event event; pushEvent(Event::Closed{});
event.type = Event::Closed;
pushEvent(event);
} }
else if (netWmPing && (windowEvent.xclient.format == 32) && else if (netWmPing && (windowEvent.xclient.format == 32) &&
(windowEvent.xclient.data.l[0]) == static_cast<long>(netWmPing)) (windowEvent.xclient.data.l[0]) == static_cast<long>(netWmPing))
@ -1815,14 +1805,13 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
{ {
// Fill the event parameters // Fill the event parameters
// TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping // TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping
Event event; Event::KeyPressed event;
event.type = Event::KeyPressed; event.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey);
event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); event.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey);
event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); event.alt = windowEvent.xkey.state & Mod1Mask;
event.key.alt = windowEvent.xkey.state & Mod1Mask; event.control = windowEvent.xkey.state & ControlMask;
event.key.control = windowEvent.xkey.state & ControlMask; event.shift = windowEvent.xkey.state & ShiftMask;
event.key.shift = windowEvent.xkey.state & ShiftMask; event.system = windowEvent.xkey.state & Mod4Mask;
event.key.system = windowEvent.xkey.state & Mod4Mask;
const bool filtered = XFilterEvent(&windowEvent, None); const bool filtered = XFilterEvent(&windowEvent, None);
@ -1876,12 +1865,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
{ {
iter = Utf8::decode(iter, keyBuffer + length, unicode, 0); iter = Utf8::decode(iter, keyBuffer + length, unicode, 0);
if (unicode != 0) if (unicode != 0)
{ pushEvent(Event::TextEntered{unicode});
Event textEvent;
textEvent.type = Event::TextEntered;
textEvent.text.unicode = unicode;
pushEvent(textEvent);
}
} }
} }
} }
@ -1891,12 +1875,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
static XComposeStatus status; static XComposeStatus status;
char keyBuffer[16]; char keyBuffer[16];
if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), nullptr, &status)) if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), nullptr, &status))
{ pushEvent(Event::TextEntered{static_cast<std::uint32_t>(keyBuffer[0])});
Event textEvent;
textEvent.type = Event::TextEntered;
textEvent.text.unicode = static_cast<std::uint32_t>(keyBuffer[0]);
pushEvent(textEvent);
}
} }
} }
@ -1909,14 +1888,13 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
case KeyRelease: case KeyRelease:
{ {
// Fill the event parameters // Fill the event parameters
Event event; Event::KeyReleased event;
event.type = Event::KeyReleased; event.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey);
event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); event.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey);
event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); event.alt = windowEvent.xkey.state & Mod1Mask;
event.key.alt = windowEvent.xkey.state & Mod1Mask; event.control = windowEvent.xkey.state & ControlMask;
event.key.control = windowEvent.xkey.state & ControlMask; event.shift = windowEvent.xkey.state & ShiftMask;
event.key.shift = windowEvent.xkey.state & ShiftMask; event.system = windowEvent.xkey.state & Mod4Mask;
event.key.system = windowEvent.xkey.state & Mod4Mask;
pushEvent(event); pushEvent(event);
break; break;
@ -1929,19 +1907,17 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
const unsigned int button = windowEvent.xbutton.button; const unsigned int button = windowEvent.xbutton.button;
if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9))
{ {
Event event; Event::MouseButtonPressed event;
event.type = Event::MouseButtonPressed; event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y};
event.mouseButton.x = windowEvent.xbutton.x;
event.mouseButton.y = windowEvent.xbutton.y;
// clang-format off // clang-format off
switch(button) switch(button)
{ {
case Button1: event.mouseButton.button = Mouse::Left; break; case Button1: event.button = Mouse::Left; break;
case Button2: event.mouseButton.button = Mouse::Middle; break; case Button2: event.button = Mouse::Middle; break;
case Button3: event.mouseButton.button = Mouse::Right; break; case Button3: event.button = Mouse::Right; break;
case 8: event.mouseButton.button = Mouse::XButton1; break; case 8: event.button = Mouse::XButton1; break;
case 9: event.mouseButton.button = Mouse::XButton2; break; case 9: event.button = Mouse::XButton2; break;
} }
// clang-format on // clang-format on
@ -1959,49 +1935,42 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
const unsigned int button = windowEvent.xbutton.button; const unsigned int button = windowEvent.xbutton.button;
if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9))
{ {
Event event; Event::MouseButtonReleased event;
event.type = Event::MouseButtonReleased; event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y};
event.mouseButton.x = windowEvent.xbutton.x;
event.mouseButton.y = windowEvent.xbutton.y;
switch (button) switch (button)
{ {
case Button1: case Button1:
event.mouseButton.button = Mouse::Left; event.button = Mouse::Left;
break; break;
case Button2: case Button2:
event.mouseButton.button = Mouse::Middle; event.button = Mouse::Middle;
break; break;
case Button3: case Button3:
event.mouseButton.button = Mouse::Right; event.button = Mouse::Right;
break; break;
case 8: case 8:
event.mouseButton.button = Mouse::XButton1; event.button = Mouse::XButton1;
break; break;
case 9: case 9:
event.mouseButton.button = Mouse::XButton2; event.button = Mouse::XButton2;
break; break;
} }
pushEvent(event); pushEvent(event);
} }
else if ((button == Button4) || (button == Button5)) else if ((button == Button4) || (button == Button5))
{ {
Event event; Event::MouseWheelScrolled event;
event.wheel = Mouse::VerticalWheel;
event.type = Event::MouseWheelScrolled; event.delta = (button == Button4) ? 1 : -1;
event.mouseWheelScroll.wheel = Mouse::VerticalWheel; event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y};
event.mouseWheelScroll.delta = (button == Button4) ? 1 : -1;
event.mouseWheelScroll.x = windowEvent.xbutton.x;
event.mouseWheelScroll.y = windowEvent.xbutton.y;
pushEvent(event); pushEvent(event);
} }
else if ((button == 6) || (button == 7)) else if ((button == 6) || (button == 7))
{ {
Event event; Event::MouseWheelScrolled event;
event.type = Event::MouseWheelScrolled; event.wheel = Mouse::HorizontalWheel;
event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; event.delta = (button == 6) ? 1 : -1;
event.mouseWheelScroll.delta = (button == 6) ? 1 : -1; event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y};
event.mouseWheelScroll.x = windowEvent.xbutton.x;
event.mouseWheelScroll.y = windowEvent.xbutton.y;
pushEvent(event); pushEvent(event);
} }
break; break;
@ -2010,11 +1979,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Mouse moved // Mouse moved
case MotionNotify: case MotionNotify:
{ {
Event event; pushEvent(Event::MouseMoved{{windowEvent.xmotion.x, windowEvent.xmotion.y}});
event.type = Event::MouseMoved;
event.mouseMove.x = windowEvent.xmotion.x;
event.mouseMove.y = windowEvent.xmotion.y;
pushEvent(event);
break; break;
} }
@ -2022,11 +1987,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
case EnterNotify: case EnterNotify:
{ {
if (windowEvent.xcrossing.mode == NotifyNormal) if (windowEvent.xcrossing.mode == NotifyNormal)
{ pushEvent(Event::MouseEntered{});
Event event;
event.type = Event::MouseEntered;
pushEvent(event);
}
break; break;
} }
@ -2034,11 +1995,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
case LeaveNotify: case LeaveNotify:
{ {
if (windowEvent.xcrossing.mode == NotifyNormal) if (windowEvent.xcrossing.mode == NotifyNormal)
{ pushEvent(Event::MouseLeft{});
Event event;
event.type = Event::MouseLeft;
pushEvent(event);
}
break; break;
} }

View File

@ -728,9 +728,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Close event // Close event
case WM_CLOSE: case WM_CLOSE:
{ {
Event event; pushEvent(Event::Closed{});
event.type = Event::Closed;
pushEvent(event);
break; break;
} }
@ -744,11 +742,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
m_lastSize = getSize(); m_lastSize = getSize();
// Push a resize event // Push a resize event
Event event; pushEvent(Event::Resized{m_lastSize});
event.type = Event::Resized;
event.size.width = m_lastSize.x;
event.size.height = m_lastSize.y;
pushEvent(event);
// Restore/update cursor grabbing // Restore/update cursor grabbing
grabCursor(m_cursorGrabbed); grabCursor(m_cursorGrabbed);
@ -776,11 +770,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
m_lastSize = getSize(); m_lastSize = getSize();
// Push a resize event // Push a resize event
Event event; pushEvent(Event::Resized{m_lastSize});
event.type = Event::Resized;
event.size.width = m_lastSize.x;
event.size.height = m_lastSize.y;
pushEvent(event);
} }
// Restore/update cursor grabbing // Restore/update cursor grabbing
@ -819,9 +809,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Restore cursor grabbing // Restore cursor grabbing
grabCursor(m_cursorGrabbed); grabCursor(m_cursorGrabbed);
Event event; pushEvent(Event::GainedFocus{});
event.type = Event::GainedFocus;
pushEvent(event);
break; break;
} }
@ -831,9 +819,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Ungrab the cursor // Ungrab the cursor
grabCursor(false); grabCursor(false);
Event event; pushEvent(Event::LostFocus{});
event.type = Event::LostFocus;
pushEvent(event);
break; break;
} }
@ -863,10 +849,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
} }
// Send a TextEntered event // Send a TextEntered event
Event event; pushEvent(Event::TextEntered{character});
event.type = Event::TextEntered;
event.text.unicode = character;
pushEvent(event);
} }
} }
break; break;
@ -878,14 +861,13 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{ {
if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0)) if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0))
{ {
Event event; Event::KeyPressed event;
event.type = Event::KeyPressed; event.alt = HIWORD(GetKeyState(VK_MENU)) != 0;
event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0; event.control = HIWORD(GetKeyState(VK_CONTROL)) != 0;
event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; event.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0;
event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; event.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN));
event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); event.code = virtualKeyCodeToSF(wParam, lParam);
event.key.code = virtualKeyCodeToSF(wParam, lParam); event.scancode = toScancode(wParam, lParam);
event.key.scancode = toScancode(wParam, lParam);
pushEvent(event); pushEvent(event);
} }
break; break;
@ -895,14 +877,13 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP: case WM_SYSKEYUP:
{ {
Event event; Event::KeyReleased event;
event.type = Event::KeyReleased; event.alt = HIWORD(GetKeyState(VK_MENU)) != 0;
event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0; event.control = HIWORD(GetKeyState(VK_CONTROL)) != 0;
event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; event.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0;
event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; event.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN));
event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); event.code = virtualKeyCodeToSF(wParam, lParam);
event.key.code = virtualKeyCodeToSF(wParam, lParam); event.scancode = toScancode(wParam, lParam);
event.key.scancode = toScancode(wParam, lParam);
pushEvent(event); pushEvent(event);
break; break;
} }
@ -918,13 +899,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
auto delta = static_cast<std::int16_t>(HIWORD(wParam)); auto delta = static_cast<std::int16_t>(HIWORD(wParam));
Event event; Event::MouseWheelScrolled event;
event.wheel = Mouse::VerticalWheel;
event.type = Event::MouseWheelScrolled; event.delta = static_cast<float>(delta) / 120.f;
event.mouseWheelScroll.wheel = Mouse::VerticalWheel; event.position = {position.x, position.y};
event.mouseWheelScroll.delta = static_cast<float>(delta) / 120.f;
event.mouseWheelScroll.x = position.x;
event.mouseWheelScroll.y = position.y;
pushEvent(event); pushEvent(event);
break; break;
} }
@ -940,12 +918,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
auto delta = static_cast<std::int16_t>(HIWORD(wParam)); auto delta = static_cast<std::int16_t>(HIWORD(wParam));
Event event; Event::MouseWheelScrolled event;
event.type = Event::MouseWheelScrolled; event.wheel = Mouse::HorizontalWheel;
event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; event.delta = -static_cast<float>(delta) / 120.f;
event.mouseWheelScroll.delta = -static_cast<float>(delta) / 120.f; event.position = {position.x, position.y};
event.mouseWheelScroll.x = position.x;
event.mouseWheelScroll.y = position.y;
pushEvent(event); pushEvent(event);
break; break;
} }
@ -953,11 +929,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse left button down event // Mouse left button down event
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
{ {
Event event; Event::MouseButtonPressed event;
event.type = Event::MouseButtonPressed; event.button = Mouse::Left;
event.mouseButton.button = Mouse::Left; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -965,11 +939,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse left button up event // Mouse left button up event
case WM_LBUTTONUP: case WM_LBUTTONUP:
{ {
Event event; Event::MouseButtonReleased event;
event.type = Event::MouseButtonReleased; event.button = Mouse::Left;
event.mouseButton.button = Mouse::Left; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -977,11 +949,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse right button down event // Mouse right button down event
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
{ {
Event event; Event::MouseButtonPressed event;
event.type = Event::MouseButtonPressed; event.button = Mouse::Right;
event.mouseButton.button = Mouse::Right; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -989,11 +959,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse right button up event // Mouse right button up event
case WM_RBUTTONUP: case WM_RBUTTONUP:
{ {
Event event; Event::MouseButtonReleased event;
event.type = Event::MouseButtonReleased; event.button = Mouse::Right;
event.mouseButton.button = Mouse::Right; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -1001,11 +969,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse wheel button down event // Mouse wheel button down event
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
{ {
Event event; Event::MouseButtonPressed event;
event.type = Event::MouseButtonPressed; event.button = Mouse::Middle;
event.mouseButton.button = Mouse::Middle; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -1013,11 +979,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse wheel button up event // Mouse wheel button up event
case WM_MBUTTONUP: case WM_MBUTTONUP:
{ {
Event event; Event::MouseButtonReleased event;
event.type = Event::MouseButtonReleased; event.button = Mouse::Middle;
event.mouseButton.button = Mouse::Middle; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -1025,11 +989,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse X button down event // Mouse X button down event
case WM_XBUTTONDOWN: case WM_XBUTTONDOWN:
{ {
Event event; Event::MouseButtonPressed event;
event.type = Event::MouseButtonPressed; event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -1037,11 +999,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
// Mouse X button up event // Mouse X button up event
case WM_XBUTTONUP: case WM_XBUTTONUP:
{ {
Event event; Event::MouseButtonReleased event;
event.type = Event::MouseButtonReleased; event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; event.position = {static_cast<std::int16_t>(LOWORD(lParam)), static_cast<std::int16_t>(HIWORD(lParam))};
event.mouseButton.x = static_cast<std::int16_t>(LOWORD(lParam));
event.mouseButton.y = static_cast<std::int16_t>(HIWORD(lParam));
pushEvent(event); pushEvent(event);
break; break;
} }
@ -1055,9 +1015,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
m_mouseInside = false; m_mouseInside = false;
// Generate a MouseLeft event // Generate a MouseLeft event
Event event; pushEvent(Event::MouseLeft{});
event.type = Event::MouseLeft;
pushEvent(event);
} }
break; break;
} }
@ -1098,9 +1056,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
setTracking(false); setTracking(false);
// Generate a MouseLeft event // Generate a MouseLeft event
Event event; pushEvent(Event::MouseLeft{});
event.type = Event::MouseLeft;
pushEvent(event);
} }
} }
else else
@ -1114,18 +1070,12 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
setTracking(true); setTracking(true);
// Generate a MouseEntered event // Generate a MouseEntered event
Event event; pushEvent(Event::MouseEntered{});
event.type = Event::MouseEntered;
pushEvent(event);
} }
} }
// Generate a MouseMove event // Generate a MouseMove event
Event event; pushEvent(Event::MouseMoved{{x, y}});
event.type = Event::MouseMoved;
event.mouseMove.x = x;
event.mouseMove.y = y;
pushEvent(event);
break; break;
} }

View File

@ -383,10 +383,10 @@ void WindowBase::onResize()
bool WindowBase::filterEvent(const Event& event) bool WindowBase::filterEvent(const Event& event)
{ {
// Notify resize events to the derived class // Notify resize events to the derived class
if (event.type == Event::Resized) if (const auto* resized = event.getIf<Event::Resized>())
{ {
// Cache the new size // Cache the new size
m_size = {event.size.width, event.size.height}; m_size = resized->size;
// Notify the derived class // Notify the derived class
onResize(); onResize();

View File

@ -234,8 +234,10 @@ void WindowImpl::processJoystickEvents()
if (previousState.connected ^ connected) if (previousState.connected ^ connected)
{ {
Event event; Event event;
event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected; if (connected)
event.joystickButton.joystickId = i; event = Event::JoystickConnected{i};
else
event = Event::JoystickDisconnected{i};
pushEvent(event); pushEvent(event);
// Clear previous axes positions // Clear previous axes positions
@ -257,13 +259,7 @@ void WindowImpl::processJoystickEvents()
const float currPos = m_joystickStatesImpl->states[i].axes[axis]; const float currPos = m_joystickStatesImpl->states[i].axes[axis];
if (std::abs(currPos - prevPos) >= m_joystickThreshold) if (std::abs(currPos - prevPos) >= m_joystickThreshold)
{ {
Event event; pushEvent(Event::JoystickMoved{i, axis, currPos});
event.type = Event::JoystickMoved;
event.joystickMove.joystickId = i;
event.joystickMove.axis = axis;
event.joystickMove.position = currPos;
pushEvent(event);
m_previousAxes[i][axis] = currPos; m_previousAxes[i][axis] = currPos;
} }
} }
@ -278,9 +274,10 @@ void WindowImpl::processJoystickEvents()
if (prevPressed ^ currPressed) if (prevPressed ^ currPressed)
{ {
Event event; Event event;
event.type = currPressed ? Event::JoystickButtonPressed : Event::JoystickButtonReleased; if (currPressed)
event.joystickButton.joystickId = i; event = Event::JoystickButtonPressed{i, j};
event.joystickButton.button = j; else
event = Event::JoystickButtonReleased{i, j};
pushEvent(event); pushEvent(event);
} }
} }
@ -308,15 +305,7 @@ void WindowImpl::processSensorEvents()
// If the value has changed, trigger an event // If the value has changed, trigger an event
if (m_sensorValue[i] != previousValue) // @todo use a threshold? if (m_sensorValue[i] != previousValue) // @todo use a threshold?
{ pushEvent(Event::SensorChanged{sensor, m_sensorValue[i]});
Event event;
event.type = Event::SensorChanged;
event.sensor.type = sensor;
event.sensor.x = m_sensorValue[i].x;
event.sensor.y = m_sensorValue[i].y;
event.sensor.z = m_sensorValue[i].z;
pushEvent(event);
}
} }
} }
} }

View File

@ -121,11 +121,7 @@ std::vector<sf::Vector2i> touchPositions;
// Generate a LostFocus event // Generate a LostFocus event
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::LostFocus{});
sf::Event event;
event.type = sf::Event::LostFocus;
sfWindow->forwardEvent(event);
}
} }
@ -145,11 +141,7 @@ std::vector<sf::Vector2i> touchPositions;
// Generate a GainedFocus event // Generate a GainedFocus event
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::GainedFocus{});
sf::Event event;
event.type = sf::Event::GainedFocus;
sfWindow->forwardEvent(event);
}
} }
@ -165,11 +157,7 @@ std::vector<sf::Vector2i> touchPositions;
{ {
// Generate a Closed event // Generate a Closed event
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::Closed{});
sf::Event event;
event.type = sf::Event::Closed;
sfWindow->forwardEvent(event);
}
} }
- (bool)supportsOrientation:(UIDeviceOrientation)orientation - (bool)supportsOrientation:(UIDeviceOrientation)orientation
@ -229,11 +217,7 @@ std::vector<sf::Vector2i> touchPositions;
std::swap(size.x, size.y); std::swap(size.x, size.y);
// Send a Resized event to the current window // Send a Resized event to the current window
sf::Event event; sfWindow->forwardEvent(sf::Event::Resized{size});
event.type = sf::Event::Resized;
event.size.width = size.x;
event.size.height = size.y;
sfWindow->forwardEvent(event);
} }
} }
} }
@ -269,14 +253,7 @@ std::vector<sf::Vector2i> touchPositions;
// notify the event to the application window // notify the event to the application window
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::TouchBegan{index, position});
sf::Event event;
event.type = sf::Event::TouchBegan;
event.touch.finger = index;
event.touch.x = position.x;
event.touch.y = position.y;
sfWindow->forwardEvent(event);
}
} }
@ -293,14 +270,7 @@ std::vector<sf::Vector2i> touchPositions;
// notify the event to the application window // notify the event to the application window
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::TouchMoved{index, position});
sf::Event event;
event.type = sf::Event::TouchMoved;
event.touch.finger = index;
event.touch.x = position.x;
event.touch.y = position.y;
sfWindow->forwardEvent(event);
}
} }
@ -313,14 +283,7 @@ std::vector<sf::Vector2i> touchPositions;
// notify the event to the application window // notify the event to the application window
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::TouchEnded{index, position * static_cast<int>(backingScaleFactor)});
sf::Event event;
event.type = sf::Event::TouchEnded;
event.touch.finger = index;
event.touch.x = position.x * static_cast<int>(backingScaleFactor);
event.touch.y = position.y * static_cast<int>(backingScaleFactor);
sfWindow->forwardEvent(event);
}
} }
@ -328,12 +291,7 @@ std::vector<sf::Vector2i> touchPositions;
- (void)notifyCharacter:(std::uint32_t)character - (void)notifyCharacter:(std::uint32_t)character
{ {
if (self.sfWindow) if (self.sfWindow)
{ sfWindow->forwardEvent(sf::Event::TextEntered{character});
sf::Event event;
event.type = sf::Event::TextEntered;
event.text.unicode = character;
sfWindow->forwardEvent(event);
}
} }

View File

@ -226,9 +226,9 @@ bool WindowImplUIKit::hasFocus() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplUIKit::forwardEvent(Event event) void WindowImplUIKit::forwardEvent(Event event)
{ {
if (event.type == Event::GainedFocus) if (event.is<Event::GainedFocus>())
m_hasFocus = true; m_hasFocus = true;
else if (event.type == Event::LostFocus) else if (event.is<Event::LostFocus>())
m_hasFocus = false; m_hasFocus = false;
pushEvent(event); pushEvent(event);

View File

@ -57,7 +57,7 @@ void initialiseKeyboardHelper();
/// \brief Set up a SFML key event based on the given modifiers flags and key code /// \brief Set up a SFML key event based on the given modifiers flags and key code
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, sf::Keyboard::Scancode code); sf::Event::KeyChanged keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, sf::Keyboard::Scancode code);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -151,16 +151,15 @@ void initialiseKeyboardHelper()
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
sf::Event::KeyEvent keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, sf::Keyboard::Scancode code) sf::Event::KeyChanged keyEventWithModifiers(NSUInteger modifiers, sf::Keyboard::Key key, sf::Keyboard::Scancode code)
{ {
sf::Event::KeyEvent event{}; sf::Event::KeyChanged event;
event.code = key; event.code = key;
event.scancode = code; event.scancode = code;
event.alt = modifiers & NSAlternateKeyMask; event.alt = modifiers & NSAlternateKeyMask;
event.control = modifiers & NSControlKeyMask; event.control = modifiers & NSControlKeyMask;
event.shift = modifiers & NSShiftKeyMask; event.shift = modifiers & NSShiftKeyMask;
event.system = modifiers & NSCommandKeyMask; event.system = modifiers & NSCommandKeyMask;
return event; return event;
} }
@ -244,19 +243,16 @@ void processOneModifier(NSUInteger modifiers,
sf::Keyboard::Scancode code, sf::Keyboard::Scancode code,
sf::priv::WindowImplCocoa& requester) sf::priv::WindowImplCocoa& requester)
{ {
// Setup a potential event key.
const sf::Event::KeyEvent event = keyEventWithModifiers(modifiers, key, code);
// State // State
const BOOL isDown = isKeyMaskActive(modifiers, mask); const BOOL isDown = isKeyMaskActive(modifiers, mask);
// Check for key pressed event // Check for key pressed event
if (isDown && !wasDown) if (isDown && !wasDown)
requester.keyDown(event); requester.keyDown(sf::Event::KeyPressed{keyEventWithModifiers(modifiers, key, code)});
// And check for key released event // And check for key released event
else if (!isDown && wasDown) else if (!isDown && wasDown)
requester.keyUp(event); requester.keyUp(sf::Event::KeyReleased{keyEventWithModifiers(modifiers, key, code)});
// else isDown == wasDown, so no change // else isDown == wasDown, so no change

View File

@ -84,7 +84,7 @@
// Handle key down event // Handle key down event
if (m_useKeyRepeat || ![theEvent isARepeat]) if (m_useKeyRepeat || ![theEvent isARepeat])
{ {
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; const auto key = sf::Event::KeyPressed{[SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]};
if ((key.code != sf::Keyboard::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown)) if ((key.code != sf::Keyboard::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown))
m_requester->keyDown(key); m_requester->keyDown(key);
@ -156,7 +156,7 @@
if (m_requester == nil) if (m_requester == nil)
return; return;
sf::Event::KeyEvent key = [SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]; const auto key = sf::Event::KeyReleased{[SFOpenGLView convertNSKeyEventToSFMLEvent:theEvent]};
if ((key.code != sf::Keyboard::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown)) if ((key.code != sf::Keyboard::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown))
m_requester->keyUp(key); m_requester->keyUp(key);
@ -178,7 +178,7 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+ (sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event + (sf::Event::KeyChanged)convertNSKeyEventToSFMLEvent:(NSEvent*)event
{ {
// The scancode always depends on the hardware keyboard, not some OS setting. // The scancode always depends on the hardware keyboard, not some OS setting.
sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]); sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]);

View File

@ -51,7 +51,7 @@
/// \return sf::Keyboard::Unknown as Code if the key is unknown /// \return sf::Keyboard::Unknown as Code if the key is unknown
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
+ (sf::Event::KeyEvent)convertNSKeyEventToSFMLEvent:(NSEvent*)event; + (sf::Event::KeyChanged)convertNSKeyEventToSFMLEvent:(NSEvent*)event;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check if the event represent some Unicode text /// \brief Check if the event represent some Unicode text

View File

@ -108,7 +108,7 @@ public:
/// \param size new width and height /// \param size new width and height
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void windowResized(const Vector2u& size); void windowResized(Vector2u size);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Window Lost Focus Event - called by the cocoa window object /// \brief Window Lost Focus Event - called by the cocoa window object
@ -195,20 +195,20 @@ public:
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param key active key /// \param event active key
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void keyDown(Event::KeyEvent key); void keyDown(Event::KeyPressed event);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Key Up Event - called by the cocoa view object /// \brief Key Up Event - called by the cocoa view object
/// ///
/// Send the event to SFML WindowImpl class. /// Send the event to SFML WindowImpl class.
/// ///
/// \param key active key /// \param event active key
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void keyUp(Event::KeyEvent key); void keyUp(Event::KeyReleased event);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Text Entred Event - called by the cocoa view object /// \brief Text Entred Event - called by the cocoa view object

View File

@ -203,23 +203,15 @@ void WindowImplCocoa::setUpProcess()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::windowClosed() void WindowImplCocoa::windowClosed()
{ {
Event event; pushEvent(Event::Closed{});
event.type = Event::Closed;
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::windowResized(const Vector2u& size) void WindowImplCocoa::windowResized(Vector2u size)
{ {
Event event; scaleOutXY(size, m_delegate);
event.type = Event::Resized; pushEvent(Event::Resized{size});
event.size.width = size.x;
event.size.height = size.y;
scaleOutWidthHeight(event.size.width, event.size.height, m_delegate);
pushEvent(event);
} }
@ -228,11 +220,7 @@ void WindowImplCocoa::windowLostFocus()
{ {
if (!m_showCursor && [m_delegate isMouseInside]) if (!m_showCursor && [m_delegate isMouseInside])
showMouseCursor(); // Make sure the cursor is visible showMouseCursor(); // Make sure the cursor is visible
pushEvent(Event::LostFocus{});
Event event;
event.type = Event::LostFocus;
pushEvent(event);
} }
@ -241,11 +229,7 @@ void WindowImplCocoa::windowGainedFocus()
{ {
if (!m_showCursor && [m_delegate isMouseInside]) if (!m_showCursor && [m_delegate isMouseInside])
hideMouseCursor(); // Restore user's setting hideMouseCursor(); // Restore user's setting
pushEvent(Event::GainedFocus{});
Event event;
event.type = Event::GainedFocus;
pushEvent(event);
} }
#pragma mark #pragma mark
@ -255,63 +239,32 @@ void WindowImplCocoa::windowGainedFocus()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseDownAt(Mouse::Button button, int x, int y) void WindowImplCocoa::mouseDownAt(Mouse::Button button, int x, int y)
{ {
Event event; scaleOutWidthHeight(x, y, m_delegate);
event.type = Event::MouseButtonPressed; pushEvent(Event::MouseButtonPressed{button, {x, y}});
event.mouseButton.button = button;
event.mouseButton.x = x;
event.mouseButton.y = y;
scaleOutXY(event.mouseButton, m_delegate);
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseUpAt(Mouse::Button button, int x, int y) void WindowImplCocoa::mouseUpAt(Mouse::Button button, int x, int y)
{ {
Event event; scaleOutWidthHeight(x, y, m_delegate);
event.type = Event::MouseButtonReleased; pushEvent(Event::MouseButtonReleased{button, {x, y}});
event.mouseButton.button = button;
event.mouseButton.x = x;
event.mouseButton.y = y;
scaleOutXY(event.mouseButton, m_delegate);
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseMovedAt(int x, int y) void WindowImplCocoa::mouseMovedAt(int x, int y)
{ {
Event event; scaleOutWidthHeight(x, y, m_delegate);
event.type = Event::MouseMoved; pushEvent(Event::MouseMoved{{x, y}});
event.mouseMove.x = x;
event.mouseMove.y = y;
scaleOutXY(event.mouseMove, m_delegate);
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y) void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y)
{ {
Event event; scaleOutWidthHeight(x, y, m_delegate);
pushEvent(Event::MouseWheelScrolled{Mouse::VerticalWheel, deltaY, {x, y}});
event.type = Event::MouseWheelScrolled; pushEvent(Event::MouseWheelScrolled{Mouse::HorizontalWheel, deltaX, {x, y}});
event.mouseWheelScroll.wheel = Mouse::VerticalWheel;
event.mouseWheelScroll.delta = deltaY;
event.mouseWheelScroll.x = x;
event.mouseWheelScroll.y = y;
scaleOutXY(event.mouseWheelScroll, m_delegate);
pushEvent(event);
event.type = Event::MouseWheelScrolled;
event.mouseWheelScroll.wheel = Mouse::HorizontalWheel;
event.mouseWheelScroll.delta = deltaX;
event.mouseWheelScroll.x = x;
event.mouseWheelScroll.y = y;
scaleOutXY(event.mouseWheelScroll, m_delegate);
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -319,11 +272,7 @@ void WindowImplCocoa::mouseMovedIn()
{ {
if (!m_showCursor) if (!m_showCursor)
hideMouseCursor(); // Restore user's setting hideMouseCursor(); // Restore user's setting
pushEvent(Event::MouseEntered{});
Event event;
event.type = Event::MouseEntered;
pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -331,11 +280,7 @@ void WindowImplCocoa::mouseMovedOut()
{ {
if (!m_showCursor) if (!m_showCursor)
showMouseCursor(); // Make sure the cursor is visible showMouseCursor(); // Make sure the cursor is visible
pushEvent(Event::MouseLeft{});
Event event;
event.type = Event::MouseLeft;
pushEvent(event);
} }
@ -344,23 +289,15 @@ void WindowImplCocoa::mouseMovedOut()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::keyDown(Event::KeyEvent key) void WindowImplCocoa::keyDown(Event::KeyPressed event)
{ {
Event event;
event.type = Event::KeyPressed;
event.key = key;
pushEvent(event); pushEvent(event);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::keyUp(Event::KeyEvent key) void WindowImplCocoa::keyUp(Event::KeyReleased event)
{ {
Event event;
event.type = Event::KeyReleased;
event.key = key;
pushEvent(event); pushEvent(event);
} }
@ -368,11 +305,7 @@ void WindowImplCocoa::keyUp(Event::KeyEvent key)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::textEntered(unichar charcode) void WindowImplCocoa::textEntered(unichar charcode)
{ {
Event event; pushEvent(Event::TextEntered{charcode});
event.type = Event::TextEntered;
event.text.unicode = charcode;
pushEvent(event);
} }

View File

@ -16,7 +16,278 @@ TEST_CASE("[Window] sf::Event")
SECTION("Construction") SECTION("Construction")
{ {
const sf::Event event{}; SECTION("Default constructor")
CHECK(event.type == sf::Event::Closed); {
const sf::Event event;
CHECK(event.getType() == sf::Event::Type::Empty);
CHECK(event.is<sf::Event::Empty>());
CHECK(event.getIf<sf::Event::Empty>() != nullptr);
STATIC_CHECK(std::is_same_v<decltype(event.get<sf::Event::Empty>()), const sf::Event::Empty&>);
}
SECTION("Template constructor")
{
const sf::Event event = sf::Event::Resized{{1, 2}};
CHECK(event.getType() == sf::Event::Type::Resized);
CHECK(event.is<sf::Event::Resized>());
CHECK(event.getIf<sf::Event::Resized>() != nullptr);
const auto& resized = event.get<sf::Event::Resized>();
CHECK(resized.size == sf::Vector2u(1, 2));
}
}
SECTION("Assign all possible values")
{
sf::Event event;
event = sf::Event::Closed{};
CHECK(event.is<sf::Event::Closed>());
CHECK(event.getType() == sf::Event::Type::Closed);
CHECK(event.getIf<sf::Event::Closed>());
event = sf::Event::Resized{{1, 2}};
CHECK(event.is<sf::Event::Resized>());
CHECK(event.getType() == sf::Event::Type::Resized);
CHECK(event.getIf<sf::Event::Resized>());
const auto& resized = event.get<sf::Event::Resized>();
CHECK(resized.size == sf::Vector2u(1, 2));
event = sf::Event::LostFocus{};
CHECK(event.is<sf::Event::LostFocus>());
CHECK(event.getType() == sf::Event::Type::LostFocus);
CHECK(event.getIf<sf::Event::LostFocus>());
event = sf::Event::GainedFocus{};
CHECK(event.is<sf::Event::GainedFocus>());
CHECK(event.getType() == sf::Event::Type::GainedFocus);
CHECK(event.getIf<sf::Event::GainedFocus>());
event = sf::Event::TextEntered{123456};
CHECK(event.is<sf::Event::TextEntered>());
CHECK(event.getType() == sf::Event::Type::TextEntered);
CHECK(event.getIf<sf::Event::TextEntered>());
const auto& textEntered = event.get<sf::Event::TextEntered>();
CHECK(textEntered.unicode == 123456);
event = sf::Event::KeyPressed{sf::Keyboard::C, sf::Keyboard::Scan::C, true, true, true, true};
CHECK(event.is<sf::Event::KeyPressed>());
CHECK(event.getType() == sf::Event::Type::KeyPressed);
CHECK(event.getIf<sf::Event::KeyPressed>());
const auto& keyPressed = event.get<sf::Event::KeyPressed>();
CHECK(keyPressed.code == sf::Keyboard::C);
CHECK(keyPressed.scancode == sf::Keyboard::Scan::C);
CHECK(keyPressed.alt);
CHECK(keyPressed.control);
CHECK(keyPressed.shift);
CHECK(keyPressed.system);
event = sf::Event::KeyReleased{sf::Keyboard::D, sf::Keyboard::Scan::D, true, true, true, true};
CHECK(event.is<sf::Event::KeyReleased>());
CHECK(event.getType() == sf::Event::Type::KeyReleased);
CHECK(event.getIf<sf::Event::KeyReleased>());
const auto& keyReleased = event.get<sf::Event::KeyReleased>();
CHECK(keyReleased.code == sf::Keyboard::D);
CHECK(keyReleased.scancode == sf::Keyboard::Scan::D);
CHECK(keyReleased.alt);
CHECK(keyReleased.control);
CHECK(keyReleased.shift);
CHECK(keyReleased.system);
event = sf::Event::MouseWheelScrolled{sf::Mouse::HorizontalWheel, 3.14f, {4, 5}};
CHECK(event.is<sf::Event::MouseWheelScrolled>());
CHECK(event.getType() == sf::Event::Type::MouseWheelScrolled);
CHECK(event.getIf<sf::Event::MouseWheelScrolled>());
const auto& mouseWheelScrolled = event.get<sf::Event::MouseWheelScrolled>();
CHECK(mouseWheelScrolled.wheel == sf::Mouse::HorizontalWheel);
CHECK(mouseWheelScrolled.delta == 3.14f);
CHECK(mouseWheelScrolled.position == sf::Vector2i(4, 5));
event = sf::Event::MouseButtonPressed{sf::Mouse::Middle, {6, 7}};
CHECK(event.is<sf::Event::MouseButtonPressed>());
CHECK(event.getType() == sf::Event::Type::MouseButtonPressed);
CHECK(event.getIf<sf::Event::MouseButtonPressed>());
const auto& mouseButtonPressed = event.get<sf::Event::MouseButtonPressed>();
CHECK(mouseButtonPressed.button == sf::Mouse::Middle);
CHECK(mouseButtonPressed.position == sf::Vector2i(6, 7));
event = sf::Event::MouseButtonReleased{sf::Mouse::XButton1, {8, 9}};
CHECK(event.is<sf::Event::MouseButtonReleased>());
CHECK(event.getType() == sf::Event::Type::MouseButtonReleased);
CHECK(event.getIf<sf::Event::MouseButtonReleased>());
const auto& mouseButtonReleased = event.get<sf::Event::MouseButtonReleased>();
CHECK(mouseButtonReleased.button == sf::Mouse::XButton1);
CHECK(mouseButtonReleased.position == sf::Vector2i(8, 9));
event = sf::Event::MouseMoved{{4, 2}};
CHECK(event.is<sf::Event::MouseMoved>());
CHECK(event.getType() == sf::Event::Type::MouseMoved);
CHECK(event.getIf<sf::Event::MouseMoved>());
const auto& mouseMoved = event.get<sf::Event::MouseMoved>();
CHECK(mouseMoved.position == sf::Vector2i(4, 2));
event = sf::Event::MouseEntered{};
CHECK(event.is<sf::Event::MouseEntered>());
CHECK(event.getType() == sf::Event::Type::MouseEntered);
CHECK(event.getIf<sf::Event::MouseEntered>());
event = sf::Event::MouseLeft{};
CHECK(event.is<sf::Event::MouseLeft>());
CHECK(event.getType() == sf::Event::Type::MouseLeft);
CHECK(event.getIf<sf::Event::MouseLeft>());
event = sf::Event::JoystickButtonPressed{100, 200};
CHECK(event.is<sf::Event::JoystickButtonPressed>());
CHECK(event.getType() == sf::Event::Type::JoystickButtonPressed);
CHECK(event.getIf<sf::Event::JoystickButtonPressed>());
const auto& joystickButtonPressed = event.get<sf::Event::JoystickButtonPressed>();
CHECK(joystickButtonPressed.joystickId == 100);
CHECK(joystickButtonPressed.button == 200);
event = sf::Event::JoystickButtonReleased{300, 400};
CHECK(event.is<sf::Event::JoystickButtonReleased>());
CHECK(event.getType() == sf::Event::Type::JoystickButtonReleased);
CHECK(event.getIf<sf::Event::JoystickButtonReleased>());
const auto& joystickButtonReleased = event.get<sf::Event::JoystickButtonReleased>();
CHECK(joystickButtonReleased.joystickId == 300);
CHECK(joystickButtonReleased.button == 400);
event = sf::Event::JoystickMoved{300, sf::Joystick::Axis::Z, 1.23f};
CHECK(event.is<sf::Event::JoystickMoved>());
CHECK(event.getType() == sf::Event::Type::JoystickMoved);
CHECK(event.getIf<sf::Event::JoystickMoved>());
const auto& joystickMoved = event.get<sf::Event::JoystickMoved>();
CHECK(joystickMoved.joystickId == 300);
CHECK(joystickMoved.axis == sf::Joystick::Axis::Z);
CHECK(joystickMoved.position == 1.23f);
event = sf::Event::JoystickConnected{42};
CHECK(event.is<sf::Event::JoystickConnected>());
CHECK(event.getType() == sf::Event::Type::JoystickConnected);
CHECK(event.getIf<sf::Event::JoystickConnected>());
const auto& joystickConnected = event.get<sf::Event::JoystickConnected>();
CHECK(joystickConnected.joystickId == 42);
event = sf::Event::JoystickDisconnected{43};
CHECK(event.is<sf::Event::JoystickDisconnected>());
CHECK(event.getType() == sf::Event::Type::JoystickDisconnected);
CHECK(event.getIf<sf::Event::JoystickDisconnected>());
const auto& joystickDisconnected = event.get<sf::Event::JoystickDisconnected>();
CHECK(joystickDisconnected.joystickId == 43);
event = sf::Event::TouchBegan{99, {98, 97}};
CHECK(event.is<sf::Event::TouchBegan>());
CHECK(event.getType() == sf::Event::Type::TouchBegan);
CHECK(event.getIf<sf::Event::TouchBegan>());
const auto& touchBegan = event.get<sf::Event::TouchBegan>();
CHECK(touchBegan.finger == 99);
CHECK(touchBegan.position == sf::Vector2i(98, 97));
event = sf::Event::TouchMoved{96, {95, 94}};
CHECK(event.is<sf::Event::TouchMoved>());
CHECK(event.getType() == sf::Event::Type::TouchMoved);
CHECK(event.getIf<sf::Event::TouchMoved>());
const auto& touchMoved = event.get<sf::Event::TouchMoved>();
CHECK(touchMoved.finger == 96);
CHECK(touchBegan.position == sf::Vector2i(95, 94));
event = sf::Event::TouchEnded{93, {92, 91}};
CHECK(event.is<sf::Event::TouchEnded>());
CHECK(event.getType() == sf::Event::Type::TouchEnded);
CHECK(event.getIf<sf::Event::TouchEnded>());
const auto& touchEnded = event.get<sf::Event::TouchEnded>();
CHECK(touchEnded.finger == 93);
CHECK(touchBegan.position == sf::Vector2i(92, 91));
event = sf::Event::SensorChanged{sf::Sensor::Type::Gravity, {1.2f, 3.4f, 5.6f}};
CHECK(event.is<sf::Event::SensorChanged>());
CHECK(event.getType() == sf::Event::Type::SensorChanged);
CHECK(event.getIf<sf::Event::SensorChanged>());
const auto& sensorChanged = event.get<sf::Event::SensorChanged>();
CHECK(sensorChanged.type == sf::Sensor::Type::Gravity);
CHECK(sensorChanged.value == sf::Vector3f(1.2f, 3.4f, 5.6f));
}
SECTION("Subtypes")
{
// Empty structs
STATIC_CHECK(std::is_empty_v<sf::Event::Empty>);
STATIC_CHECK(std::is_empty_v<sf::Event::Closed>);
STATIC_CHECK(std::is_empty_v<sf::Event::LostFocus>);
STATIC_CHECK(std::is_empty_v<sf::Event::GainedFocus>);
STATIC_CHECK(std::is_empty_v<sf::Event::MouseEntered>);
STATIC_CHECK(std::is_empty_v<sf::Event::MouseLeft>);
// Non-empty structs
const sf::Event::Resized resized;
CHECK(resized.size == sf::Vector2u());
const sf::Event::TextEntered textEntered;
CHECK(textEntered.unicode == 0);
const sf::Event::KeyPressed keyPressed;
CHECK(keyPressed.code == sf::Keyboard::Key{});
CHECK(keyPressed.scancode == sf::Keyboard::Scancode{});
CHECK(!keyPressed.alt);
CHECK(!keyPressed.control);
CHECK(!keyPressed.shift);
CHECK(!keyPressed.system);
const sf::Event::KeyReleased keyReleased;
CHECK(keyReleased.code == sf::Keyboard::Key{});
CHECK(keyReleased.scancode == sf::Keyboard::Scancode{});
CHECK(!keyReleased.alt);
CHECK(!keyReleased.control);
CHECK(!keyReleased.shift);
CHECK(!keyReleased.system);
const sf::Event::MouseWheelScrolled mouseWheelScrolled;
CHECK(mouseWheelScrolled.wheel == sf::Mouse::Wheel{});
CHECK(mouseWheelScrolled.delta == 0);
CHECK(mouseWheelScrolled.position == sf::Vector2i());
const sf::Event::MouseButtonPressed mouseButtonPressed;
CHECK(mouseButtonPressed.button == sf::Mouse::Button{});
CHECK(mouseButtonPressed.position == sf::Vector2i());
const sf::Event::MouseButtonReleased mouseButtonReleased;
CHECK(mouseButtonReleased.button == sf::Mouse::Button{});
CHECK(mouseButtonReleased.position == sf::Vector2i());
const sf::Event::MouseMoved mouseMoved;
CHECK(mouseMoved.position == sf::Vector2i());
const sf::Event::JoystickButtonPressed joystickButtonPressed;
CHECK(joystickButtonPressed.joystickId == 0);
CHECK(joystickButtonPressed.button == 0);
const sf::Event::JoystickButtonReleased joystickButtonReleased;
CHECK(joystickButtonReleased.joystickId == 0);
CHECK(joystickButtonReleased.button == 0);
const sf::Event::JoystickMoved joystickMoved;
CHECK(joystickMoved.joystickId == 0);
CHECK(joystickMoved.axis == sf::Joystick::Axis{});
CHECK(joystickMoved.position == 0);
const sf::Event::JoystickConnected joystickConnected;
CHECK(joystickConnected.joystickId == 0);
const sf::Event::JoystickDisconnected joystickDisconnected;
CHECK(joystickDisconnected.joystickId == 0);
const sf::Event::TouchBegan touchBegan;
CHECK(touchBegan.finger == 0);
CHECK(touchBegan.position == sf::Vector2i());
const sf::Event::TouchMoved touchMoved;
CHECK(touchMoved.finger == 0);
CHECK(touchMoved.position == sf::Vector2i());
const sf::Event::TouchEnded touchEnded;
CHECK(touchEnded.finger == 0);
CHECK(touchEnded.position == sf::Vector2i());
const sf::Event::SensorChanged sensorChanged;
CHECK(sensorChanged.type == sf::Sensor::Type{});
CHECK(sensorChanged.value == sf::Vector3f());
} }
} }

View File

@ -68,13 +68,13 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
{ {
window.close(); window.close();
} }
// Escape pressed: exit // Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
{ {
window.close(); window.close();
} }

View File

@ -66,13 +66,13 @@ int main()
for (sf::Event event; window.pollEvent(event);) for (sf::Event event; window.pollEvent(event);)
{ {
// Close window: exit // Close window: exit
if (event.type == sf::Event::Closed) if (event.is<sf::Event::Closed>())
{ {
window.close(); window.close();
} }
// Escape pressed: exit // Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) if (event.is<sf::Event::KeyPressed>() && event.get<sf::Event::KeyPressed>().code == sf::Keyboard::Escape)
{ {
window.close(); window.close();
} }