From 5735fd09d9bc5919947865031b6544c1f8ad7e89 Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Fri, 3 Nov 2023 21:47:14 -0600 Subject: [PATCH] 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 --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yml | 2 +- .github/pull_request_template.md | 2 +- doc/mainpage.hpp | 2 +- examples/android/app/src/main/jni/main.cpp | 34 +- examples/island/Island.cpp | 8 +- examples/joystick/Joystick.cpp | 26 +- examples/opengl/OpenGL.cpp | 15 +- examples/shader/Shader.cpp | 6 +- examples/tennis/Tennis.cpp | 10 +- examples/vulkan/Vulkan.cpp | 6 +- examples/window/Window.cpp | 11 +- include/SFML/Graphics/RenderWindow.hpp | 2 +- include/SFML/Window/Clipboard.hpp | 9 +- include/SFML/Window/Event.hpp | 460 +++++++++++++----- include/SFML/Window/Window.hpp | 4 +- include/SFML/Window/WindowBase.hpp | 4 +- src/SFML/Main/MainAndroid.cpp | 32 +- src/SFML/Window/Android/WindowImplAndroid.cpp | 88 ++-- src/SFML/Window/CMakeLists.txt | 1 + src/SFML/Window/DRM/InputImpl.cpp | 73 ++- src/SFML/Window/Event.cpp | 39 ++ src/SFML/Window/Unix/WindowImplX11.cpp | 133 ++--- src/SFML/Window/Win32/WindowImplWin32.cpp | 162 +++--- src/SFML/Window/WindowBase.cpp | 4 +- src/SFML/Window/WindowImpl.cpp | 31 +- src/SFML/Window/iOS/SFAppDelegate.mm | 58 +-- src/SFML/Window/iOS/WindowImplUIKit.mm | 4 +- .../Window/macOS/SFKeyboardModifiersHelper.h | 2 +- .../Window/macOS/SFKeyboardModifiersHelper.mm | 12 +- .../Window/macOS/SFOpenGLView+keyboard.mm | 6 +- .../Window/macOS/SFOpenGLView+keyboard_priv.h | 2 +- src/SFML/Window/macOS/WindowImplCocoa.hpp | 10 +- src/SFML/Window/macOS/WindowImplCocoa.mm | 107 +--- test/Window/Event.test.cpp | 275 ++++++++++- .../SFML/SFML App.xctemplate/main.cpp | 4 +- .../SFML/SFML CLT.xctemplate/main.cpp | 4 +- 37 files changed, 971 insertions(+), 679 deletions(-) create mode 100644 src/SFML/Window/Event.cpp diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 453fec9b6..49f871afb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -59,7 +59,7 @@ body: { for (sf::Event event; window.pollEvent(event);) { - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); } diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index fb706d71f..d1661aa2a 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -56,7 +56,7 @@ body: { for (sf::Event event; window.pollEvent(event);) { - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); } diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f68825445..4475cea18 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -41,7 +41,7 @@ int main() { for (sf::Event event; window.pollEvent(event);) { - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); } diff --git a/doc/mainpage.hpp b/doc/mainpage.hpp index d6b52f599..abd0f4824 100644 --- a/doc/mainpage.hpp +++ b/doc/mainpage.hpp @@ -47,7 +47,7 @@ /// for (sf::Event event; window.pollEvent(event);) /// { /// // Close window: exit -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// } /// diff --git a/examples/android/app/src/main/jni/main.cpp b/examples/android/app/src/main/jni/main.cpp index b90682411..26afec3da 100644 --- a/examples/android/app/src/main/jni/main.cpp +++ b/examples/android/app/src/main/jni/main.cpp @@ -115,44 +115,50 @@ int main(int argc, char* argv[]) { for (sf::Event event; active ? window.pollEvent(event) : window.waitEvent(event);) { - switch (event.type) + switch (event.getType()) { - case sf::Event::Closed: + case sf::Event::Type::Closed: window.close(); break; - case sf::Event::KeyPressed: - if (event.key.code == sf::Keyboard::Escape) + case sf::Event::Type::KeyPressed: + if (event.get().code == sf::Keyboard::Escape) window.close(); break; - case sf::Event::Resized: - view.setSize(sf::Vector2f(event.size.width, event.size.height)); - view.setCenter(sf::Vector2f(event.size.width, event.size.height) / 2.f); + case sf::Event::Type::Resized: + { + const auto size = sf::Vector2f(event.get().size); + view.setSize(size); + view.setCenter(size / 2.f); window.setView(view); break; - case sf::Event::LostFocus: + } + case sf::Event::Type::LostFocus: background = sf::Color::Black; break; - case sf::Event::GainedFocus: + case sf::Event::Type::GainedFocus: background = sf::Color::White; break; // On Android MouseLeft/MouseEntered are (for now) triggered, // whenever the app loses or gains focus. - case sf::Event::MouseLeft: + case sf::Event::Type::MouseLeft: active = false; break; - case sf::Event::MouseEntered: + case sf::Event::Type::MouseEntered: active = true; break; - case sf::Event::TouchBegan: - if (event.touch.finger == 0) + case sf::Event::Type::TouchBegan: + { + const auto& touchBegan = event.get(); + if (touchBegan.finger == 0) { - image.setPosition({static_cast(event.touch.x), static_cast(event.touch.y)}); + image.setPosition(sf::Vector2f(touchBegan.position)); #if defined(USE_JNI) vibrate(sf::milliseconds(10)); #endif } break; + } } } diff --git a/examples/island/Island.cpp b/examples/island/Island.cpp index fb28664f1..eaf6445c4 100644 --- a/examples/island/Island.cpp +++ b/examples/island/Island.cpp @@ -182,17 +182,17 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) + if (event.is() || + (event.is() && event.get().code == sf::Keyboard::Escape)) { window.close(); break; } // Arrow key pressed: - if (prerequisitesSupported && (event.type == sf::Event::KeyPressed)) + if (prerequisitesSupported && event.is()) { - switch (event.key.code) + switch (event.get().code) { case sf::Keyboard::Enter: generateTerrain(terrainStagingBuffer.data()); diff --git a/examples/joystick/Joystick.cpp b/examples/joystick/Joystick.cpp index 50af2800d..9fd61ab58 100644 --- a/examples/joystick/Joystick.cpp +++ b/examples/joystick/Joystick.cpp @@ -162,19 +162,33 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) + if (event.is() || + (event.is() && event.get().code == sf::Keyboard::Escape)) { window.close(); break; } - else if ((event.type == sf::Event::JoystickButtonPressed) || (event.type == sf::Event::JoystickButtonReleased) || - (event.type == sf::Event::JoystickMoved) || (event.type == sf::Event::JoystickConnected)) + else if (const auto* joystickButtonPressed = event.getIf()) { // 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()) + { + // Update displayed joystick values + updateValues(joystickButtonReleased->joystickId); + } + else if (const auto* joystickMoved = event.getIf()) + { + // Update displayed joystick values + updateValues(joystickMoved->joystickId); + } + else if (const auto* joystickConnected = event.getIf()) + { + // Update displayed joystick values + updateValues(joystickConnected->joystickId); + } + else if (event.is()) { // Reset displayed joystick values to empty for (auto& [label, joystickObject] : texts) diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index a3eb40814..0cfcafc43 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -207,21 +207,21 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) { exit = true; window.close(); } // Escape key: exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) + if (event.is() && event.get().code == sf::Keyboard::Escape) { exit = true; window.close(); } // Return key: toggle mipmapping - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Enter)) + if (event.is() && event.get().code == sf::Keyboard::Enter) { if (mipmapEnabled) { @@ -238,14 +238,14 @@ int main() } // Space key: toggle sRGB conversion - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) + if (event.is() && event.get().code == sf::Keyboard::Space) { sRgb = !sRgb; window.close(); } // Adjust the viewport when the window is resized - if (event.type == sf::Event::Resized) + if (const auto* resized = event.getIf()) { const sf::Vector2u textureSize = backgroundTexture.getSize(); @@ -256,10 +256,11 @@ int main() return EXIT_FAILURE; } - glViewport(0, 0, static_cast(event.size.width), static_cast(event.size.height)); + const auto [width, height] = resized->size; + glViewport(0, 0, static_cast(width), static_cast(height)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - const GLfloat newRatio = static_cast(event.size.width) / static_cast(event.size.height); + const GLfloat newRatio = static_cast(width) / static_cast(height); #ifdef SFML_OPENGL_ES glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f); #else diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index e1e4026c8..0d559089e 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -393,12 +393,12 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); - if (event.type == sf::Event::KeyPressed) + if (const auto* keyPressed = event.getIf()) { - switch (event.key.code) + switch (keyPressed->code) { // Escape key: exit case sf::Keyboard::Escape: diff --git a/examples/tennis/Tennis.cpp b/examples/tennis/Tennis.cpp index 32791dc74..ea058aa1e 100644 --- a/examples/tennis/Tennis.cpp +++ b/examples/tennis/Tennis.cpp @@ -114,16 +114,16 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) + if (event.is() || + (event.is() && event.get().code == sf::Keyboard::Escape)) { window.close(); break; } // Space key pressed: play - if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) || - (event.type == sf::Event::TouchBegan)) + if ((event.is() && event.get().code == sf::Keyboard::Space) || + event.is()) { if (!isPlaying) { @@ -146,7 +146,7 @@ int main() } // Window size changed, adjust view appropriately - if (event.type == sf::Event::Resized) + if (event.is()) { sf::View view; view.setSize({gameWidth, gameHeight}); diff --git a/examples/vulkan/Vulkan.cpp b/examples/vulkan/Vulkan.cpp index 841942d03..aeb95fe65 100644 --- a/examples/vulkan/Vulkan.cpp +++ b/examples/vulkan/Vulkan.cpp @@ -2544,15 +2544,15 @@ public: for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); // Escape key: exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) + if (event.is() && event.get().code == sf::Keyboard::Escape) window.close(); // Re-create the swapchain when the window is resized - if (event.type == sf::Event::Resized) + if (event.is()) swapchainOutOfDate = true; } diff --git a/examples/window/Window.cpp b/examples/window/Window.cpp index ce8c5ff7f..ecd883b99 100644 --- a/examples/window/Window.cpp +++ b/examples/window/Window.cpp @@ -144,20 +144,21 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) window.close(); // Escape key: exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) + if (event.is() && event.get().code == sf::Keyboard::Escape) window.close(); // Resize event: adjust the viewport - if (event.type == sf::Event::Resized) + if (const auto* resized = event.getIf()) { - glViewport(0, 0, static_cast(event.size.width), static_cast(event.size.height)); + const auto [width, height] = resized->size; + glViewport(0, 0, static_cast(width), static_cast(height)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - const GLfloat newRatio = static_cast(event.size.width) / static_cast(event.size.height); + const GLfloat newRatio = static_cast(width) / static_cast(height); #ifdef SFML_OPENGL_ES glFrustumf(-newRatio, newRatio, -1.f, 1.f, 1.f, 500.f); #else diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index eaa2036e4..90815d060 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -218,7 +218,7 @@ private: /// for (sf::Event event; window.pollEvent(event);) /// { /// // Request for closing the window -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// } /// diff --git a/include/SFML/Window/Clipboard.hpp b/include/SFML/Window/Clipboard.hpp index ddbc3a2fa..44a9b88e0 100644 --- a/include/SFML/Window/Clipboard.hpp +++ b/include/SFML/Window/Clipboard.hpp @@ -93,16 +93,17 @@ SFML_WINDOW_API void setString(const String& text); /// // or use it in the event loop /// for (sf::Event event; window.pollEvent(event);) /// { -/// if(event.type == sf::Event::Closed) +/// if(event.is()) /// window.close(); -/// if(event.type == sf::Event::KeyPressed) +/// if(event.is()) /// { +/// const auto& keyPressed = event.get(); /// // 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(); /// /// // 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!"); /// } /// } diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp index e2728abd7..3f665e0ae 100644 --- a/include/SFML/Window/Event.hpp +++ b/include/SFML/Window/Event.hpp @@ -34,8 +34,10 @@ #include #include +#include + +#include -// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) namespace sf { @@ -43,186 +45,375 @@ namespace sf /// \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 - /// (MouseButtonPressed, MouseButtonReleased) + /// \brief Gained focus event /// //////////////////////////////////////////////////////////// - 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) - 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 + std::uint32_t unicode{}; //!< UTF-32 Unicode value of the character }; //////////////////////////////////////////////////////////// - /// \brief Joystick connection events parameters - /// (JoystickConnected, JoystickDisconnected) + /// \brief KeyChanged events /// //////////////////////////////////////////////////////////// - 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]) - Joystick::Axis axis; //!< Axis on which the joystick moved - float position; //!< New position on the axis (in range [-100 .. 100]) + Mouse::Wheel wheel{}; //!< Which wheel (for mice with multiple ones) + float delta{}; //!< Wheel offset (positive is up/left, negative is down/right). High-precision mice may use non-integral offsets. + Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// - /// \brief Joystick buttons events parameters - /// (JoystickButtonPressed, JoystickButtonReleased) + /// \brief Mouse button changed events /// //////////////////////////////////////////////////////////// - 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 - 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 + Vector2i position; //!< Position of the mouse pointer, relative to the top left 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 /// + /// 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) - Resized, //!< The window was resized (data in event.size) - LostFocus, //!< The window lost the focus (no data) - GainedFocus, //!< The window gained the focus (no data) - TextEntered, //!< A character was entered (data in event.text) - KeyPressed, //!< A key was pressed (data in event.key) - KeyReleased, //!< A key was released (data in event.key) - MouseWheelScrolled, //!< The mouse wheel was scrolled (data in event.mouseWheelScroll) - MouseButtonPressed, //!< A mouse button was pressed (data in event.mouseButton) - MouseButtonReleased, //!< A mouse button was released (data in event.mouseButton) - MouseMoved, //!< The mouse cursor moved (data in event.mouseMove) - MouseEntered, //!< The mouse cursor entered the area of the window (no data) - MouseLeft, //!< The mouse cursor left the area of the window (no data) - JoystickButtonPressed, //!< A joystick button was pressed (data in event.joystickButton) - JoystickButtonReleased, //!< A joystick button was released (data in event.joystickButton) - JoystickMoved, //!< The joystick moved along an axis (data in event.joystickMove) - JoystickConnected, //!< A joystick was connected (data in event.joystickConnect) - JoystickDisconnected, //!< A joystick was disconnected (data in event.joystickConnect) - TouchBegan, //!< A touch event began (data in event.touch) - TouchMoved, //!< A touch moved (data in event.touch) - TouchEnded, //!< A touch event ended (data in event.touch) - SensorChanged, //!< A sensor value changed (data in event.sensor) - - Count //!< Keep last -- the total number of event types + Empty, //!< Default type + Closed, //!< The window requested to be closed + Resized, //!< The window was resized + LostFocus, //!< The window lost the focus + GainedFocus, //!< The window gained the focus + TextEntered, //!< A character was entered + KeyPressed, //!< A key was pressed + KeyReleased, //!< A key was released + MouseWheelScrolled, //!< The mouse wheel was scrolled + MouseButtonPressed, //!< A mouse button was pressed + MouseButtonReleased, //!< A mouse button was released + MouseMoved, //!< The mouse cursor moved + MouseEntered, //!< The mouse cursor entered the area of the window + MouseLeft, //!< The mouse cursor left the area of the window + JoystickButtonPressed, //!< A joystick button was pressed + JoystickButtonReleased, //!< A joystick button was released + JoystickMoved, //!< The joystick moved along an axis + JoystickConnected, //!< A joystick was connected + JoystickDisconnected, //!< A joystick was disconnected + TouchBegan, //!< A touch event began + TouchMoved, //!< A touch moved + TouchEnded, //!< A touch event ended + SensorChanged, //!< A sensor value changed }; +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 + static constexpr bool isInParameterPack(const std::variant&) + { + return (std::is_same_v || ...); + } + + template + static constexpr bool isEventType = isInParameterPack(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 + 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 + [[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 + [[nodiscard]] const T& get() const; + + //////////////////////////////////////////////////////////// + /// \brief Get particular event type + /// + /// \return Address of current event type, otherwise nullptr + /// + //////////////////////////////////////////////////////////// + template + [[nodiscard]] const T* getIf() const; + +private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - EventType type{}; //!< Type of the event - - 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) - }; + VariantType m_data; //!< Event data }; -} // namespace sf +//////////////////////////////////////////////////////////// +template +Event::Event(const T& t) +{ + if constexpr (isEventType) + m_data = t; + else + static_assert(isEventType, "T must be a subtype of sf::Event"); +} -// NOLINTEND(cppcoreguidelines-pro-type-member-init) +//////////////////////////////////////////////////////////// +template +bool Event::is() const +{ + if constexpr (isEventType) + return std::holds_alternative(m_data); + else + static_assert(isEventType, "T must be a subtype of sf::Event"); +} + +//////////////////////////////////////////////////////////// +template +const T& Event::get() const +{ + if constexpr (isEventType) + return std::get(m_data); + else + static_assert(isEventType, "T must be a subtype of sf::Event"); +} + +//////////////////////////////////////////////////////////// +template +const T* Event::getIf() const +{ + if constexpr (isEventType) + return std::get_if(&m_data); + else + static_assert(isEventType, "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 /// (mouse moved, key pressed, window closed, ...) as well -/// as the details about this particular event. Please note that -/// the event parameters are defined in a union, which means that -/// only the member matching the type of the event will be properly -/// filled; all other members will have undefined values and must not -/// be read if the type of the event doesn't match. For example, -/// if you received a KeyPressed event, then you must read the -/// event.key member, all other members such as event.mouseMove -/// or event.text will have undefined values. +/// as the details about this particular event. Each event +/// corresponds to a different struct which contains the data +/// required to process that event. +/// +/// Various member functions are provided to inspect the current +/// active event and access it's data. These functions give you +/// multiple options for how you choose to process events. +/// +/// 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().code == sf::Keyboard::Escape) +/// window.close(); +/// break; +/// +/// // The window was resized +/// case sf::Event::Type::Resized: +/// doSomethingWithTheNewSize(event.get().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 /// for (sf::Event event; window.pollEvent(event);) /// { /// // Request for closing the window -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// /// // The escape key was pressed -/// if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) -/// window.close(); +/// if (const auto* keyPressed = event.getIf()) +/// if (keyPressed->code == sf::Keyboard::Escape) +/// window.close(); /// /// // The window was resized -/// if (event.type == sf::Event::Resized) -/// doSomethingWithTheNewSize(event.size.width, event.size.height); +/// if (const auto* resized = event.getIf()) +/// doSomethingWithTheNewSize(resized->size); /// /// // etc ... /// } diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 9dc73dbf3..d366c0622 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -44,7 +44,7 @@ namespace priv class GlContext; } -struct Event; +class Event; //////////////////////////////////////////////////////////// /// \brief Window that serves as a target for OpenGL rendering @@ -338,7 +338,7 @@ private: /// for (sf::Event event; window.pollEvent(event);) /// { /// // Request for closing the window -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// } /// diff --git a/include/SFML/Window/WindowBase.hpp b/include/SFML/Window/WindowBase.hpp index 26a60294b..11f380957 100644 --- a/include/SFML/Window/WindowBase.hpp +++ b/include/SFML/Window/WindowBase.hpp @@ -50,7 +50,7 @@ namespace priv class WindowImpl; } -struct Event; +class Event; //////////////////////////////////////////////////////////// /// \brief Window that serves as a base for other windows @@ -535,7 +535,7 @@ private: /// for (sf::Event event; window.pollEvent(event);) /// { /// // Request for closing the window -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// } /// diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index f424d23bc..4783faedd 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -268,10 +268,7 @@ static void onResume(ANativeActivity* activity) goToFullscreenMode(activity); // Send an event to warn people the activity has been resumed - sf::Event event; - event.type = sf::Event::MouseEntered; - - states->forwardEvent(event); + states->forwardEvent(sf::Event::MouseEntered{}); } @@ -283,10 +280,7 @@ static void onPause(ANativeActivity* activity) std::lock_guard lock(states->mutex); // Send an event to warn people the activity has been paused - sf::Event event; - event.type = sf::Event::MouseLeft; - - states->forwardEvent(event); + states->forwardEvent(sf::Event::MouseLeft{}); } @@ -309,12 +303,7 @@ static void onDestroy(ANativeActivity* activity) // If the main thread hasn't yet finished, send the event and wait for // it to finish. if (!states->mainOver) - { - sf::Event event; - event.type = sf::Event::Closed; - - states->forwardEvent(event); - } + states->forwardEvent(sf::Event::Closed{}); } // Wait for the main thread to be terminated @@ -352,9 +341,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind states->window = window; // Notify SFML mechanism - sf::Event event; - event.type = sf::Event::GainedFocus; - states->forwardEvent(event); + states->forwardEvent(sf::Event::GainedFocus{}); // Wait for the event to be taken into account by SFML states->updated = false; @@ -377,9 +364,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* /* states->window = nullptr; // Notify SFML mechanism - sf::Event event; - event.type = sf::Event::LostFocus; - states->forwardEvent(event); + states->forwardEvent(sf::Event::LostFocus{}); // Wait for the event to be taken into account by SFML states->updated = false; @@ -455,11 +440,8 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* /* rect if (states->window != nullptr) { // Send an event to warn people about the window move/resize - sf::Event event; - event.type = sf::Event::Resized; - event.size.width = static_cast(ANativeWindow_getWidth(states->window)); - event.size.height = static_cast(ANativeWindow_getHeight(states->window)); - + const sf::Event::Resized event{ + sf::Vector2u(sf::Vector2(ANativeWindow_getWidth(states->window), ANativeWindow_getHeight(states->window)))}; states->forwardEvent(event); } } diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index f6c8b8023..072890bba 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -233,14 +233,14 @@ void WindowImplAndroid::forwardEvent(const Event& event) { ActivityStates& states = getActivity(); - if (event.type == Event::GainedFocus) + if (event.is()) { WindowImplAndroid::singleInstance->m_size = Vector2u( Vector2i(ANativeWindow_getWidth(states.window), ANativeWindow_getHeight(states.window))); WindowImplAndroid::singleInstance->m_windowBeingCreated = true; WindowImplAndroid::singleInstance->m_hasFocus = true; } - else if (event.type == Event::LostFocus) + else if (event.is()) { WindowImplAndroid::singleInstance->m_windowBeingDestroyed = true; WindowImplAndroid::singleInstance->m_hasFocus = false; @@ -391,13 +391,10 @@ int WindowImplAndroid::processScrollEvent(AInputEvent* inputEvent, ActivityState lJNIEnv->DeleteLocalRef(objectMotionEvent); // Create and send our mouse wheel event - Event event; - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::VerticalWheel; - event.mouseWheelScroll.delta = static_cast(delta); - event.mouseWheelScroll.x = static_cast(AMotionEvent_getX(inputEvent, 0)); - event.mouseWheelScroll.y = static_cast(AMotionEvent_getY(inputEvent, 0)); - + Event::MouseWheelScrolled event; + event.wheel = Mouse::VerticalWheel; + event.delta = static_cast(delta); + event.position = Vector2i(Vector2(AMotionEvent_getX(inputEvent, 0), AMotionEvent_getY(inputEvent, 0))); forwardEvent(event); // 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 metakey = AKeyEvent_getMetaState(inputEvent); - Event event; - event.key.code = androidKeyToSF(key); - event.key.alt = metakey & AMETA_ALT_ON; - event.key.control = false; - event.key.shift = metakey & AMETA_SHIFT_ON; + Event::KeyChanged keyChanged; + keyChanged.code = androidKeyToSF(key); + keyChanged.alt = metakey & AMETA_ALT_ON; + keyChanged.control = false; + keyChanged.shift = metakey & AMETA_SHIFT_ON; switch (action) { case AKEY_EVENT_ACTION_DOWN: - event.type = Event::KeyPressed; - forwardEvent(event); + forwardEvent(Event::KeyPressed{keyChanged}); return 1; case AKEY_EVENT_ACTION_UP: - event.type = Event::KeyReleased; - forwardEvent(event); + forwardEvent(Event::KeyReleased{keyChanged}); if (auto unicode = static_cast(getUnicode(inputEvent))) - { - event.type = Event::TextEntered; - event.text.unicode = static_cast(unicode); - forwardEvent(event); - } + forwardEvent(Event::TextEntered{static_cast(unicode)}); return 1; case AKEY_EVENT_ACTION_MULTIPLE: // Since complex inputs don't get separate key down/up events // both have to be faked at once - event.type = Event::KeyPressed; - forwardEvent(event); - event.type = Event::KeyReleased; - forwardEvent(event); + forwardEvent(Event::KeyPressed{keyChanged}); + forwardEvent(Event::KeyReleased{keyChanged}); // This requires some special treatment, since this might represent // 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(getUnicode(inputEvent))) // This is a repeated sequence { - event.type = Event::TextEntered; - event.text.unicode = static_cast(unicode); + const Event event(Event::TextEntered{static_cast(unicode)}); std::int32_t repeats = AKeyEvent_getRepeatCount(inputEvent); for (std::int32_t i = 0; i < repeats; ++i) @@ -478,9 +466,9 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* inputEvent, ActivityState Event event; if (device == AINPUT_SOURCE_MOUSE) - event.type = Event::MouseMoved; + event = Event::MouseMoved{}; else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) - event.type = Event::TouchMoved; + event = Event::TouchMoved{}; std::size_t pointerCount = AMotionEvent_getPointerCount(inputEvent); @@ -493,21 +481,20 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* inputEvent, ActivityState if (device == AINPUT_SOURCE_MOUSE) { - event.mouseMove.x = x; - event.mouseMove.y = y; + const Event::MouseMoved mouseMoved{{x, y}}; + event = mouseMoved; - states.mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y); + states.mousePosition = mouseMoved.position; } else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) { if (states.touchEvents[id].x == x && states.touchEvents[id].y == y) continue; - event.touch.finger = static_cast(id); - event.touch.x = x; - event.touch.y = y; + const Event::TouchMoved touchMoved{static_cast(id), {x, y}}; + event = touchMoved; - states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y); + states.touchEvents[id] = touchMoved.position; } forwardEvent(event); @@ -534,42 +521,33 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent, { if (device == AINPUT_SOURCE_MOUSE) { - event.type = Event::MouseButtonPressed; - event.mouseButton.button = static_cast(id); - event.mouseButton.x = x; - event.mouseButton.y = y; + event = Event::MouseButtonPressed{static_cast(id), {x, y}}; if (id >= 0 && id < Mouse::ButtonCount) states.isButtonPressed[id] = true; } else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) { - event.type = Event::TouchBegan; - event.touch.finger = static_cast(id); - event.touch.x = x; - event.touch.y = y; + Event::TouchBegan touchBegan; + touchBegan.finger = static_cast(id); + touchBegan.position = {x, y}; + event = touchBegan; - states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y); + states.touchEvents[id] = touchBegan.position; } } else { if (device == AINPUT_SOURCE_MOUSE) { - event.type = Event::MouseButtonReleased; - event.mouseButton.button = static_cast(id); - event.mouseButton.x = x; - event.mouseButton.y = y; + event = Event::MouseButtonReleased{static_cast(id), {x, y}}; if (id >= 0 && id < Mouse::ButtonCount) states.isButtonPressed[id] = false; } else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) { - event.type = Event::TouchEnded; - event.touch.finger = static_cast(id); - event.touch.x = x; - event.touch.y = y; + event = Event::TouchEnded{static_cast(id), {x, y}}; states.touchEvents.erase(id); } diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 589544592..465dbb2d4 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -19,6 +19,7 @@ set(SRC ${INCROOT}/GlResource.hpp ${INCROOT}/ContextSettings.hpp ${INCROOT}/Event.hpp + ${SRCROOT}/Event.cpp ${SRCROOT}/InputImpl.hpp ${INCROOT}/Joystick.hpp ${SRCROOT}/Joystick.cpp diff --git a/src/SFML/Window/DRM/InputImpl.cpp b/src/SFML/Window/DRM/InputImpl.cpp index a2d60c836..63a21a1e9 100644 --- a/src/SFML/Window/DRM/InputImpl.cpp +++ b/src/SFML/Window/DRM/InputImpl.cpp @@ -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) eventQueue.pop(); @@ -323,31 +323,16 @@ void processSlots() { for (auto& slot : touchSlots) { - sf::Event event; - - event.touch.x = slot.pos.x; - event.touch.y = slot.pos.y; - if (slot.oldId == slot.id) { - event.type = sf::Event::TouchMoved; - event.touch.finger = static_cast(slot.id); - pushEvent(event); + pushEvent(sf::Event::TouchMoved{static_cast(slot.id), slot.pos}); } else { if (slot.oldId != -1) - { - event.type = sf::Event::TouchEnded; - event.touch.finger = static_cast(slot.oldId); - pushEvent(event); - } + pushEvent(sf::Event::TouchEnded{static_cast(slot.oldId), slot.pos}); if (slot.id != -1) - { - event.type = sf::Event::TouchBegan; - event.touch.finger = static_cast(slot.id); - pushEvent(event); - } + pushEvent(sf::Event::TouchBegan{static_cast(slot.id), slot.pos}); slot.oldId = slot.id; } @@ -366,9 +351,8 @@ bool eventProcess(sf::Event& event) static unsigned int doDeferredText = 0; if (doDeferredText) { - event.type = sf::Event::TextEntered; - event.text.unicode = doDeferredText; - doDeferredText = 0; + event = sf::Event::TextEntered{doDeferredText}; + doDeferredText = 0; return true; } @@ -387,10 +371,10 @@ bool eventProcess(sf::Event& event) const sf::Mouse::Button mb = toMouseButton(inputEvent.code); if (mb != sf::Mouse::ButtonCount) { - event.type = inputEvent.value ? sf::Event::MouseButtonPressed : sf::Event::MouseButtonReleased; - event.mouseButton.button = mb; - event.mouseButton.x = mousePos.x; - event.mouseButton.y = mousePos.y; + if (inputEvent.value) + event = sf::Event::MouseButtonPressed{mb, mousePos}; + else + event = sf::Event::MouseButtonReleased{mb, mousePos}; mouseMap[mb] = inputEvent.value; return true; @@ -409,8 +393,7 @@ bool eventProcess(sf::Event& event) // if (special) { - event.type = sf::Event::TextEntered; - event.text.unicode = special; + event = sf::Event::TextEntered{special}; return true; } } @@ -418,13 +401,18 @@ bool eventProcess(sf::Event& event) { // key down and key up events // - event.type = inputEvent.value ? sf::Event::KeyPressed : sf::Event::KeyReleased; - event.key.code = kb; - event.key.scancode = sf::Keyboard::Scan::Unknown; // TODO: not implemented - event.key.alt = altDown(); - event.key.control = controlDown(); - event.key.shift = shiftDown(); - event.key.system = systemDown(); + sf::Event::KeyChanged keyChanged; + keyChanged.code = kb; + keyChanged.scancode = sf::Keyboard::Scan::Unknown; // TODO: not implemented + keyChanged.alt = altDown(); + keyChanged.control = controlDown(); + keyChanged.shift = shiftDown(); + keyChanged.system = systemDown(); + + if (inputEvent.value) + event = sf::Event::KeyPressed{keyChanged}; + else + event = sf::Event::KeyReleased{keyChanged}; keyMap[static_cast(kb)] = inputEvent.value; @@ -451,18 +439,16 @@ bool eventProcess(sf::Event& event) break; case REL_WHEEL: - event.type = sf::Event::MouseWheelScrolled; - event.mouseWheelScroll.delta = static_cast(inputEvent.value); - event.mouseWheelScroll.x = mousePos.x; - event.mouseWheelScroll.y = mousePos.y; + sf::Event::MouseWheelScrolled mouseWheelScrolled; + mouseWheelScrolled.delta = static_cast(inputEvent.value); + mouseWheelScrolled.position = mousePos; + event = mouseWheelScrolled; return true; } if (posChange) { - event.type = sf::Event::MouseMoved; - event.mouseMove.x = mousePos.x; - event.mouseMove.y = mousePos.y; + event = sf::Event::MouseMoved{mousePos}; return true; } } @@ -547,8 +533,7 @@ bool eventProcess(sf::Event& event) if (code > 0) { // TODO: Proper unicode handling - event.type = sf::Event::TextEntered; - event.text.unicode = code; + event = sf::Event::TextEntered{code}; return true; } diff --git a/src/SFML/Window/Event.cpp b/src/SFML/Window/Event.cpp new file mode 100644 index 000000000..022ab8985 --- /dev/null +++ b/src/SFML/Window/Event.cpp @@ -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 + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Event::Type Event::getType() const +{ + return static_cast(m_data.index()); +} + +} // namespace sf diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 81a60cc79..86c9e76d6 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1720,9 +1720,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) err() << "Failed to grab mouse cursor" << std::endl; } - Event event; - event.type = Event::GainedFocus; - pushEvent(event); + pushEvent(Event::GainedFocus{}); // If the window has been previously marked urgent (notification) as a result of a focus request, undo that auto hints = X11Ptr(XGetWMHints(m_display, m_window)); @@ -1747,9 +1745,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) if (m_cursorGrabbed) XUngrabPointer(m_display, CurrentTime); - Event event; - event.type = Event::LostFocus; - pushEvent(event); + pushEvent(Event::LostFocus{}); break; } @@ -1759,11 +1755,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) // 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)) { - Event event; - event.type = Event::Resized; - event.size.width = static_cast(windowEvent.xconfigure.width); - event.size.height = static_cast(windowEvent.xconfigure.height); - pushEvent(event); + pushEvent(Event::Resized{Vector2u(Vector2(windowEvent.xconfigure.width, windowEvent.xconfigure.height))}); m_previousSize.x = windowEvent.xconfigure.width; m_previousSize.y = windowEvent.xconfigure.height; @@ -1789,9 +1781,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) (windowEvent.xclient.data.l[0]) == static_cast(wmDeleteWindow)) { // Handle the WM_DELETE_WINDOW message - Event event; - event.type = Event::Closed; - pushEvent(event); + pushEvent(Event::Closed{}); } else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(netWmPing)) @@ -1815,14 +1805,13 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) { // Fill the event parameters // TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping - Event event; - event.type = Event::KeyPressed; - event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); - event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); - event.key.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + Event::KeyPressed event; + event.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); + event.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); + event.alt = windowEvent.xkey.state & Mod1Mask; + event.control = windowEvent.xkey.state & ControlMask; + event.shift = windowEvent.xkey.state & ShiftMask; + event.system = windowEvent.xkey.state & Mod4Mask; const bool filtered = XFilterEvent(&windowEvent, None); @@ -1876,12 +1865,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) { iter = Utf8::decode(iter, keyBuffer + length, unicode, 0); if (unicode != 0) - { - Event textEvent; - textEvent.type = Event::TextEntered; - textEvent.text.unicode = unicode; - pushEvent(textEvent); - } + pushEvent(Event::TextEntered{unicode}); } } } @@ -1891,12 +1875,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) static XComposeStatus status; char keyBuffer[16]; if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), nullptr, &status)) - { - Event textEvent; - textEvent.type = Event::TextEntered; - textEvent.text.unicode = static_cast(keyBuffer[0]); - pushEvent(textEvent); - } + pushEvent(Event::TextEntered{static_cast(keyBuffer[0])}); } } @@ -1909,14 +1888,13 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) case KeyRelease: { // Fill the event parameters - Event event; - event.type = Event::KeyReleased; - event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); - event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); - event.key.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + Event::KeyReleased event; + event.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); + event.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); + event.alt = windowEvent.xkey.state & Mod1Mask; + event.control = windowEvent.xkey.state & ControlMask; + event.shift = windowEvent.xkey.state & ShiftMask; + event.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); break; @@ -1929,19 +1907,17 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) const unsigned int button = windowEvent.xbutton.button; if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.x = windowEvent.xbutton.x; - event.mouseButton.y = windowEvent.xbutton.y; + Event::MouseButtonPressed event; + event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y}; // clang-format off switch(button) { - case Button1: event.mouseButton.button = Mouse::Left; break; - case Button2: event.mouseButton.button = Mouse::Middle; break; - case Button3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.button = Mouse::Left; break; + case Button2: event.button = Mouse::Middle; break; + case Button3: event.button = Mouse::Right; break; + case 8: event.button = Mouse::XButton1; break; + case 9: event.button = Mouse::XButton2; break; } // clang-format on @@ -1959,49 +1935,42 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) const unsigned int button = windowEvent.xbutton.button; if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.x = windowEvent.xbutton.x; - event.mouseButton.y = windowEvent.xbutton.y; + Event::MouseButtonReleased event; + event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y}; switch (button) { case Button1: - event.mouseButton.button = Mouse::Left; + event.button = Mouse::Left; break; case Button2: - event.mouseButton.button = Mouse::Middle; + event.button = Mouse::Middle; break; case Button3: - event.mouseButton.button = Mouse::Right; + event.button = Mouse::Right; break; case 8: - event.mouseButton.button = Mouse::XButton1; + event.button = Mouse::XButton1; break; case 9: - event.mouseButton.button = Mouse::XButton2; + event.button = Mouse::XButton2; break; } pushEvent(event); } else if ((button == Button4) || (button == Button5)) { - Event event; - - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::VerticalWheel; - event.mouseWheelScroll.delta = (button == Button4) ? 1 : -1; - event.mouseWheelScroll.x = windowEvent.xbutton.x; - event.mouseWheelScroll.y = windowEvent.xbutton.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::VerticalWheel; + event.delta = (button == Button4) ? 1 : -1; + event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y}; pushEvent(event); } else if ((button == 6) || (button == 7)) { - Event event; - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; - event.mouseWheelScroll.delta = (button == 6) ? 1 : -1; - event.mouseWheelScroll.x = windowEvent.xbutton.x; - event.mouseWheelScroll.y = windowEvent.xbutton.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::HorizontalWheel; + event.delta = (button == 6) ? 1 : -1; + event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y}; pushEvent(event); } break; @@ -2010,11 +1979,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) // Mouse moved case MotionNotify: { - Event event; - event.type = Event::MouseMoved; - event.mouseMove.x = windowEvent.xmotion.x; - event.mouseMove.y = windowEvent.xmotion.y; - pushEvent(event); + pushEvent(Event::MouseMoved{{windowEvent.xmotion.x, windowEvent.xmotion.y}}); break; } @@ -2022,11 +1987,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) case EnterNotify: { if (windowEvent.xcrossing.mode == NotifyNormal) - { - Event event; - event.type = Event::MouseEntered; - pushEvent(event); - } + pushEvent(Event::MouseEntered{}); break; } @@ -2034,11 +1995,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) case LeaveNotify: { if (windowEvent.xcrossing.mode == NotifyNormal) - { - Event event; - event.type = Event::MouseLeft; - pushEvent(event); - } + pushEvent(Event::MouseLeft{}); break; } diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 57a0fe021..536a5e5f7 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -728,9 +728,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Close event case WM_CLOSE: { - Event event; - event.type = Event::Closed; - pushEvent(event); + pushEvent(Event::Closed{}); break; } @@ -744,11 +742,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) m_lastSize = getSize(); // Push a resize event - Event event; - event.type = Event::Resized; - event.size.width = m_lastSize.x; - event.size.height = m_lastSize.y; - pushEvent(event); + pushEvent(Event::Resized{m_lastSize}); // Restore/update cursor grabbing grabCursor(m_cursorGrabbed); @@ -776,11 +770,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) m_lastSize = getSize(); // Push a resize event - Event event; - event.type = Event::Resized; - event.size.width = m_lastSize.x; - event.size.height = m_lastSize.y; - pushEvent(event); + pushEvent(Event::Resized{m_lastSize}); } // Restore/update cursor grabbing @@ -819,9 +809,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Restore cursor grabbing grabCursor(m_cursorGrabbed); - Event event; - event.type = Event::GainedFocus; - pushEvent(event); + pushEvent(Event::GainedFocus{}); break; } @@ -831,9 +819,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Ungrab the cursor grabCursor(false); - Event event; - event.type = Event::LostFocus; - pushEvent(event); + pushEvent(Event::LostFocus{}); break; } @@ -863,10 +849,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) } // Send a TextEntered event - Event event; - event.type = Event::TextEntered; - event.text.unicode = character; - pushEvent(event); + pushEvent(Event::TextEntered{character}); } } break; @@ -878,14 +861,13 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) { if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0)) { - Event event; - event.type = Event::KeyPressed; - event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0; - event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; - event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; - event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); - event.key.code = virtualKeyCodeToSF(wParam, lParam); - event.key.scancode = toScancode(wParam, lParam); + Event::KeyPressed event; + event.alt = HIWORD(GetKeyState(VK_MENU)) != 0; + event.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; + event.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; + event.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); + event.code = virtualKeyCodeToSF(wParam, lParam); + event.scancode = toScancode(wParam, lParam); pushEvent(event); } break; @@ -895,14 +877,13 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) case WM_KEYUP: case WM_SYSKEYUP: { - Event event; - event.type = Event::KeyReleased; - event.key.alt = HIWORD(GetKeyState(VK_MENU)) != 0; - event.key.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; - event.key.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; - event.key.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); - event.key.code = virtualKeyCodeToSF(wParam, lParam); - event.key.scancode = toScancode(wParam, lParam); + Event::KeyReleased event; + event.alt = HIWORD(GetKeyState(VK_MENU)) != 0; + event.control = HIWORD(GetKeyState(VK_CONTROL)) != 0; + event.shift = HIWORD(GetKeyState(VK_SHIFT)) != 0; + event.system = HIWORD(GetKeyState(VK_LWIN)) || HIWORD(GetKeyState(VK_RWIN)); + event.code = virtualKeyCodeToSF(wParam, lParam); + event.scancode = toScancode(wParam, lParam); pushEvent(event); break; } @@ -918,13 +899,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) auto delta = static_cast(HIWORD(wParam)); - Event event; - - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::VerticalWheel; - event.mouseWheelScroll.delta = static_cast(delta) / 120.f; - event.mouseWheelScroll.x = position.x; - event.mouseWheelScroll.y = position.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::VerticalWheel; + event.delta = static_cast(delta) / 120.f; + event.position = {position.x, position.y}; pushEvent(event); break; } @@ -940,12 +918,10 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) auto delta = static_cast(HIWORD(wParam)); - Event event; - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; - event.mouseWheelScroll.delta = -static_cast(delta) / 120.f; - event.mouseWheelScroll.x = position.x; - event.mouseWheelScroll.y = position.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::HorizontalWheel; + event.delta = -static_cast(delta) / 120.f; + event.position = {position.x, position.y}; pushEvent(event); break; } @@ -953,11 +929,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse left button down event case WM_LBUTTONDOWN: { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Left; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -965,11 +939,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse left button up event case WM_LBUTTONUP: { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Left; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -977,11 +949,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse right button down event case WM_RBUTTONDOWN: { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Right; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -989,11 +959,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse right button up event case WM_RBUTTONUP: { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Right; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1001,11 +969,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse wheel button down event case WM_MBUTTONDOWN: { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Middle; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1013,11 +979,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse wheel button up event case WM_MBUTTONUP: { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Middle; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1025,11 +989,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse X button down event case WM_XBUTTONDOWN: { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1037,11 +999,9 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) // Mouse X button up event case WM_XBUTTONUP: { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1055,9 +1015,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) m_mouseInside = false; // Generate a MouseLeft event - Event event; - event.type = Event::MouseLeft; - pushEvent(event); + pushEvent(Event::MouseLeft{}); } break; } @@ -1098,9 +1056,7 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) setTracking(false); // Generate a MouseLeft event - Event event; - event.type = Event::MouseLeft; - pushEvent(event); + pushEvent(Event::MouseLeft{}); } } else @@ -1114,18 +1070,12 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) setTracking(true); // Generate a MouseEntered event - Event event; - event.type = Event::MouseEntered; - pushEvent(event); + pushEvent(Event::MouseEntered{}); } } // Generate a MouseMove event - Event event; - event.type = Event::MouseMoved; - event.mouseMove.x = x; - event.mouseMove.y = y; - pushEvent(event); + pushEvent(Event::MouseMoved{{x, y}}); break; } diff --git a/src/SFML/Window/WindowBase.cpp b/src/SFML/Window/WindowBase.cpp index 9be065b28..ed2476e13 100644 --- a/src/SFML/Window/WindowBase.cpp +++ b/src/SFML/Window/WindowBase.cpp @@ -383,10 +383,10 @@ void WindowBase::onResize() bool WindowBase::filterEvent(const Event& event) { // Notify resize events to the derived class - if (event.type == Event::Resized) + if (const auto* resized = event.getIf()) { // Cache the new size - m_size = {event.size.width, event.size.height}; + m_size = resized->size; // Notify the derived class onResize(); diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 0f0a00eec..d75d87751 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -234,8 +234,10 @@ void WindowImpl::processJoystickEvents() if (previousState.connected ^ connected) { Event event; - event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected; - event.joystickButton.joystickId = i; + if (connected) + event = Event::JoystickConnected{i}; + else + event = Event::JoystickDisconnected{i}; pushEvent(event); // Clear previous axes positions @@ -257,13 +259,7 @@ void WindowImpl::processJoystickEvents() const float currPos = m_joystickStatesImpl->states[i].axes[axis]; if (std::abs(currPos - prevPos) >= m_joystickThreshold) { - Event event; - event.type = Event::JoystickMoved; - event.joystickMove.joystickId = i; - event.joystickMove.axis = axis; - event.joystickMove.position = currPos; - pushEvent(event); - + pushEvent(Event::JoystickMoved{i, axis, currPos}); m_previousAxes[i][axis] = currPos; } } @@ -278,9 +274,10 @@ void WindowImpl::processJoystickEvents() if (prevPressed ^ currPressed) { Event event; - event.type = currPressed ? Event::JoystickButtonPressed : Event::JoystickButtonReleased; - event.joystickButton.joystickId = i; - event.joystickButton.button = j; + if (currPressed) + event = Event::JoystickButtonPressed{i, j}; + else + event = Event::JoystickButtonReleased{i, j}; pushEvent(event); } } @@ -308,15 +305,7 @@ void WindowImpl::processSensorEvents() // If the value has changed, trigger an event if (m_sensorValue[i] != previousValue) // @todo use a threshold? - { - 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); - } + pushEvent(Event::SensorChanged{sensor, m_sensorValue[i]}); } } } diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm index 5a38cd303..1360769f7 100644 --- a/src/SFML/Window/iOS/SFAppDelegate.mm +++ b/src/SFML/Window/iOS/SFAppDelegate.mm @@ -121,11 +121,7 @@ std::vector touchPositions; // Generate a LostFocus event if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::LostFocus; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::LostFocus{}); } @@ -145,11 +141,7 @@ std::vector touchPositions; // Generate a GainedFocus event if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::GainedFocus; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::GainedFocus{}); } @@ -165,11 +157,7 @@ std::vector touchPositions; { // Generate a Closed event if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::Closed; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::Closed{}); } - (bool)supportsOrientation:(UIDeviceOrientation)orientation @@ -229,11 +217,7 @@ std::vector touchPositions; std::swap(size.x, size.y); // Send a Resized event to the current window - sf::Event event; - event.type = sf::Event::Resized; - event.size.width = size.x; - event.size.height = size.y; - sfWindow->forwardEvent(event); + sfWindow->forwardEvent(sf::Event::Resized{size}); } } } @@ -269,14 +253,7 @@ std::vector touchPositions; // notify the event to the application window if (self.sfWindow) - { - 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); - } + sfWindow->forwardEvent(sf::Event::TouchBegan{index, position}); } @@ -293,14 +270,7 @@ std::vector touchPositions; // notify the event to the application window if (self.sfWindow) - { - 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); - } + sfWindow->forwardEvent(sf::Event::TouchMoved{index, position}); } @@ -313,14 +283,7 @@ std::vector touchPositions; // notify the event to the application window if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::TouchEnded; - event.touch.finger = index; - event.touch.x = position.x * static_cast(backingScaleFactor); - event.touch.y = position.y * static_cast(backingScaleFactor); - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::TouchEnded{index, position * static_cast(backingScaleFactor)}); } @@ -328,12 +291,7 @@ std::vector touchPositions; - (void)notifyCharacter:(std::uint32_t)character { if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::TextEntered; - event.text.unicode = character; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::TextEntered{character}); } diff --git a/src/SFML/Window/iOS/WindowImplUIKit.mm b/src/SFML/Window/iOS/WindowImplUIKit.mm index 05d66bd42..4a1770307 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.mm +++ b/src/SFML/Window/iOS/WindowImplUIKit.mm @@ -226,9 +226,9 @@ bool WindowImplUIKit::hasFocus() const //////////////////////////////////////////////////////////// void WindowImplUIKit::forwardEvent(Event event) { - if (event.type == Event::GainedFocus) + if (event.is()) m_hasFocus = true; - else if (event.type == Event::LostFocus) + else if (event.is()) m_hasFocus = false; pushEvent(event); diff --git a/src/SFML/Window/macOS/SFKeyboardModifiersHelper.h b/src/SFML/Window/macOS/SFKeyboardModifiersHelper.h index 6dea869ce..f68fa800b 100644 --- a/src/SFML/Window/macOS/SFKeyboardModifiersHelper.h +++ b/src/SFML/Window/macOS/SFKeyboardModifiersHelper.h @@ -57,7 +57,7 @@ void initialiseKeyboardHelper(); /// \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); //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/macOS/SFKeyboardModifiersHelper.mm b/src/SFML/Window/macOS/SFKeyboardModifiersHelper.mm index 55629f3f3..a7b3883a7 100644 --- a/src/SFML/Window/macOS/SFKeyboardModifiersHelper.mm +++ b/src/SFML/Window/macOS/SFKeyboardModifiersHelper.mm @@ -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.scancode = code; event.alt = modifiers & NSAlternateKeyMask; event.control = modifiers & NSControlKeyMask; event.shift = modifiers & NSShiftKeyMask; event.system = modifiers & NSCommandKeyMask; - return event; } @@ -244,19 +243,16 @@ void processOneModifier(NSUInteger modifiers, sf::Keyboard::Scancode code, sf::priv::WindowImplCocoa& requester) { - // Setup a potential event key. - const sf::Event::KeyEvent event = keyEventWithModifiers(modifiers, key, code); - // State const BOOL isDown = isKeyMaskActive(modifiers, mask); // Check for key pressed event if (isDown && !wasDown) - requester.keyDown(event); + requester.keyDown(sf::Event::KeyPressed{keyEventWithModifiers(modifiers, key, code)}); // And check for key released event else if (!isDown && wasDown) - requester.keyUp(event); + requester.keyUp(sf::Event::KeyReleased{keyEventWithModifiers(modifiers, key, code)}); // else isDown == wasDown, so no change diff --git a/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm b/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm index 526f06cd4..e0aeb714e 100644 --- a/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm +++ b/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm @@ -84,7 +84,7 @@ // Handle key down event 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)) m_requester->keyDown(key); @@ -156,7 +156,7 @@ if (m_requester == nil) 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)) 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. sf::Keyboard::Scancode code = sf::priv::HIDInputManager::nonLocalizedKey([event keyCode]); diff --git a/src/SFML/Window/macOS/SFOpenGLView+keyboard_priv.h b/src/SFML/Window/macOS/SFOpenGLView+keyboard_priv.h index 2bf7894a8..e51b72fb3 100644 --- a/src/SFML/Window/macOS/SFOpenGLView+keyboard_priv.h +++ b/src/SFML/Window/macOS/SFOpenGLView+keyboard_priv.h @@ -51,7 +51,7 @@ /// \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 diff --git a/src/SFML/Window/macOS/WindowImplCocoa.hpp b/src/SFML/Window/macOS/WindowImplCocoa.hpp index 8d3dd14c3..32100aa07 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.hpp +++ b/src/SFML/Window/macOS/WindowImplCocoa.hpp @@ -108,7 +108,7 @@ public: /// \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 @@ -195,20 +195,20 @@ public: /// /// 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 /// /// 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 diff --git a/src/SFML/Window/macOS/WindowImplCocoa.mm b/src/SFML/Window/macOS/WindowImplCocoa.mm index 36876b894..4d647516e 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.mm +++ b/src/SFML/Window/macOS/WindowImplCocoa.mm @@ -203,23 +203,15 @@ void WindowImplCocoa::setUpProcess() //////////////////////////////////////////////////////////// void WindowImplCocoa::windowClosed() { - Event event; - event.type = Event::Closed; - - pushEvent(event); + pushEvent(Event::Closed{}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::windowResized(const Vector2u& size) +void WindowImplCocoa::windowResized(Vector2u size) { - Event event; - event.type = Event::Resized; - event.size.width = size.x; - event.size.height = size.y; - scaleOutWidthHeight(event.size.width, event.size.height, m_delegate); - - pushEvent(event); + scaleOutXY(size, m_delegate); + pushEvent(Event::Resized{size}); } @@ -228,11 +220,7 @@ void WindowImplCocoa::windowLostFocus() { if (!m_showCursor && [m_delegate isMouseInside]) showMouseCursor(); // Make sure the cursor is visible - - Event event; - event.type = Event::LostFocus; - - pushEvent(event); + pushEvent(Event::LostFocus{}); } @@ -241,11 +229,7 @@ void WindowImplCocoa::windowGainedFocus() { if (!m_showCursor && [m_delegate isMouseInside]) hideMouseCursor(); // Restore user's setting - - Event event; - event.type = Event::GainedFocus; - - pushEvent(event); + pushEvent(Event::GainedFocus{}); } #pragma mark @@ -255,63 +239,32 @@ void WindowImplCocoa::windowGainedFocus() //////////////////////////////////////////////////////////// void WindowImplCocoa::mouseDownAt(Mouse::Button button, int x, int y) { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = button; - event.mouseButton.x = x; - event.mouseButton.y = y; - scaleOutXY(event.mouseButton, m_delegate); - - pushEvent(event); + scaleOutWidthHeight(x, y, m_delegate); + pushEvent(Event::MouseButtonPressed{button, {x, y}}); } //////////////////////////////////////////////////////////// void WindowImplCocoa::mouseUpAt(Mouse::Button button, int x, int y) { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = button; - event.mouseButton.x = x; - event.mouseButton.y = y; - scaleOutXY(event.mouseButton, m_delegate); - - pushEvent(event); + scaleOutWidthHeight(x, y, m_delegate); + pushEvent(Event::MouseButtonReleased{button, {x, y}}); } //////////////////////////////////////////////////////////// void WindowImplCocoa::mouseMovedAt(int x, int y) { - Event event; - event.type = Event::MouseMoved; - event.mouseMove.x = x; - event.mouseMove.y = y; - scaleOutXY(event.mouseMove, m_delegate); - - pushEvent(event); + scaleOutWidthHeight(x, y, m_delegate); + pushEvent(Event::MouseMoved{{x, y}}); } //////////////////////////////////////////////////////////// void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y) { - Event event; - - event.type = Event::MouseWheelScrolled; - 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); + scaleOutWidthHeight(x, y, m_delegate); + pushEvent(Event::MouseWheelScrolled{Mouse::VerticalWheel, deltaY, {x, y}}); + pushEvent(Event::MouseWheelScrolled{Mouse::HorizontalWheel, deltaX, {x, y}}); } //////////////////////////////////////////////////////////// @@ -319,11 +272,7 @@ void WindowImplCocoa::mouseMovedIn() { if (!m_showCursor) hideMouseCursor(); // Restore user's setting - - Event event; - event.type = Event::MouseEntered; - - pushEvent(event); + pushEvent(Event::MouseEntered{}); } //////////////////////////////////////////////////////////// @@ -331,11 +280,7 @@ void WindowImplCocoa::mouseMovedOut() { if (!m_showCursor) showMouseCursor(); // Make sure the cursor is visible - - Event event; - event.type = Event::MouseLeft; - - pushEvent(event); + pushEvent(Event::MouseLeft{}); } @@ -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); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::keyUp(Event::KeyEvent key) +void WindowImplCocoa::keyUp(Event::KeyReleased event) { - Event event; - event.type = Event::KeyReleased; - event.key = key; - pushEvent(event); } @@ -368,11 +305,7 @@ void WindowImplCocoa::keyUp(Event::KeyEvent key) //////////////////////////////////////////////////////////// void WindowImplCocoa::textEntered(unichar charcode) { - Event event; - event.type = Event::TextEntered; - event.text.unicode = charcode; - - pushEvent(event); + pushEvent(Event::TextEntered{charcode}); } diff --git a/test/Window/Event.test.cpp b/test/Window/Event.test.cpp index 1fbf65a39..bbfd707be 100644 --- a/test/Window/Event.test.cpp +++ b/test/Window/Event.test.cpp @@ -16,7 +16,278 @@ TEST_CASE("[Window] sf::Event") SECTION("Construction") { - const sf::Event event{}; - CHECK(event.type == sf::Event::Closed); + SECTION("Default constructor") + { + const sf::Event event; + CHECK(event.getType() == sf::Event::Type::Empty); + CHECK(event.is()); + CHECK(event.getIf() != nullptr); + STATIC_CHECK(std::is_same_v()), 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()); + CHECK(event.getIf() != nullptr); + const auto& resized = event.get(); + CHECK(resized.size == sf::Vector2u(1, 2)); + } + } + + SECTION("Assign all possible values") + { + sf::Event event; + event = sf::Event::Closed{}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::Closed); + CHECK(event.getIf()); + + event = sf::Event::Resized{{1, 2}}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::Resized); + CHECK(event.getIf()); + const auto& resized = event.get(); + CHECK(resized.size == sf::Vector2u(1, 2)); + + event = sf::Event::LostFocus{}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::LostFocus); + CHECK(event.getIf()); + + event = sf::Event::GainedFocus{}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::GainedFocus); + CHECK(event.getIf()); + + event = sf::Event::TextEntered{123456}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::TextEntered); + CHECK(event.getIf()); + const auto& textEntered = event.get(); + CHECK(textEntered.unicode == 123456); + + event = sf::Event::KeyPressed{sf::Keyboard::C, sf::Keyboard::Scan::C, true, true, true, true}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::KeyPressed); + CHECK(event.getIf()); + const auto& keyPressed = event.get(); + 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()); + CHECK(event.getType() == sf::Event::Type::KeyReleased); + CHECK(event.getIf()); + const auto& keyReleased = event.get(); + 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()); + CHECK(event.getType() == sf::Event::Type::MouseWheelScrolled); + CHECK(event.getIf()); + const auto& mouseWheelScrolled = event.get(); + 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()); + CHECK(event.getType() == sf::Event::Type::MouseButtonPressed); + CHECK(event.getIf()); + const auto& mouseButtonPressed = event.get(); + 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()); + CHECK(event.getType() == sf::Event::Type::MouseButtonReleased); + CHECK(event.getIf()); + const auto& mouseButtonReleased = event.get(); + CHECK(mouseButtonReleased.button == sf::Mouse::XButton1); + CHECK(mouseButtonReleased.position == sf::Vector2i(8, 9)); + + event = sf::Event::MouseMoved{{4, 2}}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::MouseMoved); + CHECK(event.getIf()); + const auto& mouseMoved = event.get(); + CHECK(mouseMoved.position == sf::Vector2i(4, 2)); + + event = sf::Event::MouseEntered{}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::MouseEntered); + CHECK(event.getIf()); + + event = sf::Event::MouseLeft{}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::MouseLeft); + CHECK(event.getIf()); + + event = sf::Event::JoystickButtonPressed{100, 200}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::JoystickButtonPressed); + CHECK(event.getIf()); + const auto& joystickButtonPressed = event.get(); + CHECK(joystickButtonPressed.joystickId == 100); + CHECK(joystickButtonPressed.button == 200); + + event = sf::Event::JoystickButtonReleased{300, 400}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::JoystickButtonReleased); + CHECK(event.getIf()); + const auto& joystickButtonReleased = event.get(); + CHECK(joystickButtonReleased.joystickId == 300); + CHECK(joystickButtonReleased.button == 400); + + event = sf::Event::JoystickMoved{300, sf::Joystick::Axis::Z, 1.23f}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::JoystickMoved); + CHECK(event.getIf()); + const auto& joystickMoved = event.get(); + CHECK(joystickMoved.joystickId == 300); + CHECK(joystickMoved.axis == sf::Joystick::Axis::Z); + CHECK(joystickMoved.position == 1.23f); + + event = sf::Event::JoystickConnected{42}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::JoystickConnected); + CHECK(event.getIf()); + const auto& joystickConnected = event.get(); + CHECK(joystickConnected.joystickId == 42); + + event = sf::Event::JoystickDisconnected{43}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::JoystickDisconnected); + CHECK(event.getIf()); + const auto& joystickDisconnected = event.get(); + CHECK(joystickDisconnected.joystickId == 43); + + event = sf::Event::TouchBegan{99, {98, 97}}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::TouchBegan); + CHECK(event.getIf()); + const auto& touchBegan = event.get(); + CHECK(touchBegan.finger == 99); + CHECK(touchBegan.position == sf::Vector2i(98, 97)); + + event = sf::Event::TouchMoved{96, {95, 94}}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::TouchMoved); + CHECK(event.getIf()); + const auto& touchMoved = event.get(); + CHECK(touchMoved.finger == 96); + CHECK(touchBegan.position == sf::Vector2i(95, 94)); + + event = sf::Event::TouchEnded{93, {92, 91}}; + CHECK(event.is()); + CHECK(event.getType() == sf::Event::Type::TouchEnded); + CHECK(event.getIf()); + const auto& touchEnded = event.get(); + 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()); + CHECK(event.getType() == sf::Event::Type::SensorChanged); + CHECK(event.getIf()); + const auto& sensorChanged = event.get(); + 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); + STATIC_CHECK(std::is_empty_v); + STATIC_CHECK(std::is_empty_v); + STATIC_CHECK(std::is_empty_v); + STATIC_CHECK(std::is_empty_v); + STATIC_CHECK(std::is_empty_v); + + // 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()); } } diff --git a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp index c2b32be99..4dd6d18f4 100644 --- a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp @@ -68,13 +68,13 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) { window.close(); } // Escape pressed: exit - if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) + if (event.is() && event.get().code == sf::Keyboard::Escape) { window.close(); } diff --git a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp index 1ad9be987..d90dddc5d 100644 --- a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp @@ -66,13 +66,13 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) { window.close(); } // Escape pressed: exit - if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) + if (event.is() && event.get().code == sf::Keyboard::Escape) { window.close(); }