From 59447dd8e50c9e354bc8730862b99bdfab2eaeb1 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 | 75 ++-- examples/island/Island.cpp | 8 +- examples/joystick/Joystick.cpp | 26 +- examples/opengl/OpenGL.cpp | 18 +- examples/shader/Shader.cpp | 6 +- examples/sound_effects/SoundEffects.cpp | 8 +- examples/stencil/Stencil.cpp | 2 +- examples/tennis/Tennis.cpp | 10 +- examples/vulkan/Vulkan.cpp | 7 +- examples/window/Window.cpp | 14 +- include/SFML/Graphics/RenderWindow.hpp | 2 +- include/SFML/Window/Clipboard.hpp | 8 +- include/SFML/Window/Event.hpp | 328 ++++++++++++------ include/SFML/Window/Event.inl | 60 ++++ include/SFML/Window/Window.hpp | 2 +- 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/Unix/WindowImplX11.cpp | 133 +++---- src/SFML/Window/Win32/WindowImplWin32.cpp | 162 +++------ src/SFML/Window/WindowBase.cpp | 4 +- src/SFML/Window/WindowImpl.cpp | 35 +- src/SFML/Window/iOS/SFAppDelegate.mm | 62 +--- 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/SFOpenGLView+mouse.mm | 9 +- src/SFML/Window/macOS/SFOpenGLView.mm | 4 +- src/SFML/Window/macOS/Scaling.h | 7 - src/SFML/Window/macOS/WindowImplCocoa.hpp | 42 +-- src/SFML/Window/macOS/WindowImplCocoa.mm | 119 ++----- .../Window/macOS/WindowImplDelegateProtocol.h | 2 +- test/Window/Event.test.cpp | 250 ++++++++++++- .../SFML/SFML App.xctemplate/main.cpp | 5 +- .../SFML/SFML CLT.xctemplate/main.cpp | 5 +- 43 files changed, 895 insertions(+), 750 deletions(-) create mode 100644 include/SFML/Window/Event.inl diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 453fec9b6f..49f871afbf 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 fb706d71f5..d1661aa2a5 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 f68825445d..4475cea18e 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 d6b52f5994..abd0f48241 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 d381081dfa..9e704506b2 100644 --- a/examples/android/app/src/main/jni/main.cpp +++ b/examples/android/app/src/main/jni/main.cpp @@ -115,46 +115,49 @@ int main(int argc, char* argv[]) { for (sf::Event event; active ? window.pollEvent(event) : window.waitEvent(event);) { - switch (event.type) + if (event.is()) { - case sf::Event::Closed: + window.close(); + } + else if (const auto* keyPressed = event.getIf()) + { + if (keyPressed->code == sf::Keyboard::Key::Escape) window.close(); - break; - case sf::Event::KeyPressed: - if (event.key.code == sf::Keyboard::Key::Escape) - window.close(); - break; - case sf::Event::Resized: - view.setSize(sf::Vector2f(event.size.width, event.size.height)); - view.setCenter(sf::Vector2f(event.size.width, event.size.height) / 2.f); - window.setView(view); - break; - case sf::Event::LostFocus: - background = sf::Color::Black; - break; - case sf::Event::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: - active = false; - break; - case sf::Event::MouseEntered: - active = true; - break; - case sf::Event::TouchBegan: - if (event.touch.finger == 0) - { - image.setPosition({static_cast(event.touch.x), static_cast(event.touch.y)}); + } + else if (const auto* resized = event.getIf()) + { + const auto size = sf::Vector2f(resized->size); + view.setSize(size); + view.setCenter(size / 2.f); + window.setView(view); + } + else if (event.is()) + { + background = sf::Color::Black; + } + else if (event.is()) + { + background = sf::Color::White; + } + // On Android MouseLeft/MouseEntered are (for now) triggered, + // whenever the app loses or gains focus. + else if (event.is()) + { + active = false; + } + else if (event.is()) + { + active = true; + } + else if (const auto* touchBegan = event.getIf()) + { + if (touchBegan->finger == 0) + { + image.setPosition(sf::Vector2f(touchBegan->position)); #if defined(USE_JNI) - vibrate(sf::milliseconds(10)); + vibrate(sf::milliseconds(10)); #endif - } - break; - default: - break; + } } } diff --git a/examples/island/Island.cpp b/examples/island/Island.cpp index 8c35d631aa..c389a34340 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::Key::Escape))) + if (event.is() || (event.is() && + event.getIf()->code == sf::Keyboard::Key::Escape)) { window.close(); break; } // Arrow key pressed: - if (prerequisitesSupported && (event.type == sf::Event::KeyPressed)) + if (prerequisitesSupported && event.is()) { - switch (event.key.code) + switch (event.getIf()->code) { case sf::Keyboard::Key::Enter: generateTerrain(terrainStagingBuffer.data()); diff --git a/examples/joystick/Joystick.cpp b/examples/joystick/Joystick.cpp index 1f7d795cac..a4cf88d49f 100644 --- a/examples/joystick/Joystick.cpp +++ b/examples/joystick/Joystick.cpp @@ -161,19 +161,33 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape))) + if (event.is() || (event.is() && + event.getIf()->code == sf::Keyboard::Key::Escape)) { window.close(); break; } - else if ((event.type == sf::Event::JoystickButtonPressed) || (event.type == sf::Event::JoystickButtonReleased) || - (event.type == sf::Event::JoystickMoved) || (event.type == sf::Event::JoystickConnected)) + else if (const auto* joystickButtonPressed = event.getIf()) { // 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 477e58cf37..6e526aed20 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -211,21 +211,23 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Close window: exit - if (event.type == sf::Event::Closed) + if (event.is()) { exit = true; window.close(); } // Escape key: exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape)) + if (const auto* keyPressed = event.getIf(); + keyPressed && keyPressed->code == sf::Keyboard::Key::Escape) { exit = true; window.close(); } // Return key: toggle mipmapping - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Enter)) + if (const auto* keyPressed = event.getIf(); + keyPressed && keyPressed->code == sf::Keyboard::Key::Enter) { if (mipmapEnabled) { @@ -242,14 +244,15 @@ int main() } // Space key: toggle sRGB conversion - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Space)) + if (const auto* keyPressed = event.getIf(); + keyPressed && keyPressed->code == sf::Keyboard::Key::Space) { sRgb = !sRgb; window.close(); } // Adjust the viewport when the window is resized - if (event.type == sf::Event::Resized) + if (const auto* resized = event.getIf()) { const sf::Vector2u textureSize = backgroundTexture.getSize(); @@ -260,10 +263,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 50da66f5bc..8be184c343 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -392,12 +392,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::Key::Escape: diff --git a/examples/sound_effects/SoundEffects.cpp b/examples/sound_effects/SoundEffects.cpp index 23cb55b916..79651f208b 100644 --- a/examples/sound_effects/SoundEffects.cpp +++ b/examples/sound_effects/SoundEffects.cpp @@ -680,12 +680,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::Key::Escape: @@ -715,7 +715,7 @@ int main() break; default: - effects[current]->handleKey(event.key.code); + effects[current]->handleKey(keyPressed->code); break; } } diff --git a/examples/stencil/Stencil.cpp b/examples/stencil/Stencil.cpp index beacde5172..e79005dbf2 100644 --- a/examples/stencil/Stencil.cpp +++ b/examples/stencil/Stencil.cpp @@ -43,7 +43,7 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed: exit - if (event.type == sf::Event::Closed) + if (event.is()) { window.close(); break; diff --git a/examples/tennis/Tennis.cpp b/examples/tennis/Tennis.cpp index cf7b6e6b7f..18ba7b8e88 100644 --- a/examples/tennis/Tennis.cpp +++ b/examples/tennis/Tennis.cpp @@ -118,16 +118,16 @@ int main() for (sf::Event event; window.pollEvent(event);) { // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Escape))) + if (event.is() || (event.is() && + event.getIf()->code == sf::Keyboard::Key::Escape)) { window.close(); break; } // Space key pressed: play - if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Key::Space)) || - (event.type == sf::Event::TouchBegan)) + if ((event.is() && event.getIf()->code == sf::Keyboard::Key::Space) || + event.is()) { if (!isPlaying) { @@ -150,7 +150,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 120c842a55..7f026ae1f7 100644 --- a/examples/vulkan/Vulkan.cpp +++ b/examples/vulkan/Vulkan.cpp @@ -2545,15 +2545,16 @@ class VulkanExample 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::Key::Escape)) + if (event.is() && + event.getIf()->code == sf::Keyboard::Key::Escape) window.close(); // Re-create the swapchain when the window is resized - if (event.type == sf::Event::Resized) + if (event.is()) swapchainOutOfDate = true; } diff --git a/examples/window/Window.cpp b/examples/window/Window.cpp index 3d038beeb7..2aaa7a4467 100644 --- a/examples/window/Window.cpp +++ b/examples/window/Window.cpp @@ -144,20 +144,22 @@ 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::Key::Escape)) - window.close(); + if (const auto* keyPressed = event.getIf()) + if (keyPressed->code == sf::Keyboard::Key::Escape) + window.close(); // Resize event: adjust the viewport - if (event.type == sf::Event::Resized) + if (const auto* resized = event.getIf()) { - 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 28e9bf3bdd..052b1c964b 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -240,7 +240,7 @@ class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget /// for (sf::Event event; window.pollEvent(event);) /// { /// // Request for closing the window -/// if (event.type == sf::Event::Closed) +/// if (event.is()) /// window.close(); /// } /// diff --git a/include/SFML/Window/Clipboard.hpp b/include/SFML/Window/Clipboard.hpp index 5a05823bce..0d28a2d65a 100644 --- a/include/SFML/Window/Clipboard.hpp +++ b/include/SFML/Window/Clipboard.hpp @@ -93,16 +93,16 @@ 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(const auto* keyPressed = event.getIf()) /// { /// // Using Ctrl + V to paste a string into SFML -/// if(event.key.control && event.key.code == sf::Keyboard::Key::V) +/// if(keyPressed->control && keyPressed->code == sf::Keyboard::Key::V) /// string = sf::Clipboard::getString(); /// /// // Using Ctrl + C to copy a string out of SFML -/// if(event.key.control && event.key.code == sf::Keyboard::Key::C) +/// if(keyPressed->control && keyPressed->code == sf::Keyboard::Key::C) /// sf::Clipboard::setString("Hello World!"); /// } /// } diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp index ed0891aa38..1b0b2169ce 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,282 @@ 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 FocusLost { - 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 FocusGained { - 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 Enumeration of the different types of events + /// \brief Mouse left event /// //////////////////////////////////////////////////////////// - enum EventType + struct MouseLeft { - 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 }; //////////////////////////////////////////////////////////// - // Member data + /// \brief Joystick button events + /// //////////////////////////////////////////////////////////// - EventType type{}; //!< Type of the event + 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 + { + }; - union + //////////////////////////////////////////////////////////// + /// \brief Joystick axis move event + /// + //////////////////////////////////////////////////////////// + struct JoystickMoved { - 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) + 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 Default constructor + /// + /// Sets the event to sf::Event::Empty + /// + //////////////////////////////////////////////////////////// + Event() = default; + + //////////////////////////////////////////////////////////// + /// \brief Construct from a given sf::Event subtype + /// + /// \param t Event subtype + /// + //////////////////////////////////////////////////////////// + template + Event(const T& t); + + //////////////////////////////////////////////////////////// + /// \brief Check current event type + /// + /// \return True if template parameter is current event type + /// + //////////////////////////////////////////////////////////// + template + [[nodiscard]] bool is() const; + + //////////////////////////////////////////////////////////// + /// \brief Get particular event type + /// + /// \return Address of current event type, otherwise nullptr + /// + //////////////////////////////////////////////////////////// + template + [[nodiscard]] const T* getIf() const; + +private: + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::variant + m_data; //!< Event data + + //////////////////////////////////////////////////////////// + // Helper functions + //////////////////////////////////////////////////////////// + template + static constexpr bool isInParameterPack(const std::variant&) + { + return (std::is_same_v || ...); + } + + template + static constexpr bool isEventType = isInParameterPack(decltype(m_data)()); }; -} // namespace sf +#include -// NOLINTEND(cppcoreguidelines-pro-type-member-init) +} // namespace sf //////////////////////////////////////////////////////////// @@ -235,30 +333,32 @@ 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. +/// +/// The way to access the current active event is via +/// sf::Event::getIf. This member function returns the address +/// of the event struct if the event type matches the active +/// event, otherise it returns nullptr. sf::Event::is is used +/// to check the active event type without actually reading +/// any of the corresponding event data. /// -/// 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::Key::Escape)) -/// window.close(); +/// if (const auto* keyPressed = event.getIf()) +/// if (keyPressed->code == sf::Keyboard::Key::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/Event.inl b/include/SFML/Window/Event.inl new file mode 100644 index 0000000000..eded3de394 --- /dev/null +++ b/include/SFML/Window/Event.inl @@ -0,0 +1,60 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2024 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. +// +//////////////////////////////////////////////////////////// + +// Repeating isEventType allows for cleaner compiler errors. +// It is not strictly necessary but it's useful nonetheless. +// It works by ensuring that the code within the conditional is +// only compiled when the condition is met. Otherwise you get +// a static_assert failure in addition to the compiler failing +// to compile the code within the compiletime conditional when +// an incorrect template parameter is provided. + +//////////////////////////////////////////////////////////// +template +Event::Event(const T& t) +{ + static_assert(isEventType, "T must be a subtype of sf::Event"); + if constexpr (isEventType) + m_data = t; +} + + +//////////////////////////////////////////////////////////// +template +bool Event::is() const +{ + static_assert(isEventType, "T must be a subtype of sf::Event"); + if constexpr (isEventType) + return std::holds_alternative(m_data); +} + + +//////////////////////////////////////////////////////////// +template +const T* Event::getIf() const +{ + static_assert(isEventType, "T must be a subtype of sf::Event"); + if constexpr (isEventType) + return std::get_if(&m_data); +} diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 0037a0e922..0ac10e6633 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -350,7 +350,7 @@ class SFML_WINDOW_API Window : public WindowBase, GlResource /// 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 8a4474bb6d..c1e75ce7ea 100644 --- a/include/SFML/Window/WindowBase.hpp +++ b/include/SFML/Window/WindowBase.hpp @@ -52,7 +52,7 @@ namespace priv class WindowImpl; } -struct Event; +class Event; //////////////////////////////////////////////////////////// /// \brief Window that serves as a base for other windows @@ -566,7 +566,7 @@ class SFML_WINDOW_API WindowBase /// 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 600546b773..630ad9fff9 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -266,10 +266,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{}); } @@ -281,10 +278,7 @@ static void onPause(ANativeActivity* activity) const 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{}); } @@ -307,12 +301,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 @@ -350,9 +339,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::FocusGained{}); // Wait for the event to be taken into account by SFML states->updated = false; @@ -375,9 +362,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::FocusLost{}); // Wait for the event to be taken into account by SFML states->updated = false; @@ -453,11 +438,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 c856ba9c64..41e5532085 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -234,14 +234,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; @@ -392,13 +392,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::Wheel::Vertical; - 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::Wheel::Vertical; + 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 @@ -416,36 +413,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 @@ -457,8 +446,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) @@ -479,9 +467,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); @@ -494,21 +482,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); @@ -536,42 +523,33 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent, { if (device == AINPUT_SOURCE_MOUSE) { - event.type = Event::MouseButtonPressed; - event.mouseButton.button = button; - event.mouseButton.x = x; - event.mouseButton.y = y; + event = Event::MouseButtonPressed{button, {x, y}}; if (id >= 0 && id < static_cast(Mouse::ButtonCount)) states.isButtonPressed[button] = 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 = button; - event.mouseButton.x = x; - event.mouseButton.y = y; + event = Event::MouseButtonReleased{button, {x, y}}; if (id >= 0 && id < static_cast(Mouse::ButtonCount)) states.isButtonPressed[button] = 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 c2993a3acb..8e3dd85546 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -18,6 +18,7 @@ set(SRC ${INCROOT}/GlResource.hpp ${INCROOT}/ContextSettings.hpp ${INCROOT}/Event.hpp + ${INCROOT}/Event.inl ${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 7e5d536fe1..028437859c 100644 --- a/src/SFML/Window/DRM/InputImpl.cpp +++ b/src/SFML/Window/DRM/InputImpl.cpp @@ -306,7 +306,7 @@ sf::Keyboard::Key toKey(int code) } } -void pushEvent(sf::Event& event) +void pushEvent(const sf::Event& event) { if (eventQueue.size() >= maxQueue) eventQueue.pop(); @@ -325,31 +325,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; } @@ -368,9 +353,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; } @@ -388,10 +372,10 @@ bool eventProcess(sf::Event& event) { if (const std::optional mb = toMouseButton(inputEvent.code)) { - 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; @@ -410,8 +394,7 @@ bool eventProcess(sf::Event& event) // if (special) { - event.type = sf::Event::TextEntered; - event.text.unicode = special; + event = sf::Event::TextEntered{special}; return true; } } @@ -419,13 +402,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[kb] = inputEvent.value; @@ -452,18 +440,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; } } @@ -548,8 +534,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/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 23e2e453e0..0b05955d17 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1712,9 +1712,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) err() << "Failed to grab mouse cursor" << std::endl; } - Event event; - event.type = Event::GainedFocus; - pushEvent(event); + pushEvent(Event::FocusGained{}); // If the window has been previously marked urgent (notification) as a result of a focus request, undo that const auto hints = X11Ptr(XGetWMHints(m_display.get(), m_window)); @@ -1739,9 +1737,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) if (m_cursorGrabbed) XUngrabPointer(m_display.get(), CurrentTime); - Event event; - event.type = Event::LostFocus; - pushEvent(event); + pushEvent(Event::FocusLost{}); break; } @@ -1751,11 +1747,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; @@ -1781,9 +1773,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)) @@ -1807,14 +1797,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); @@ -1868,12 +1857,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}); } } } @@ -1883,12 +1867,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])}); } } @@ -1901,14 +1880,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; @@ -1921,19 +1899,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::Button::Left; break; - case Button2: event.mouseButton.button = Mouse::Button::Middle; break; - case Button3: event.mouseButton.button = Mouse::Button::Right; break; - case 8: event.mouseButton.button = Mouse::Button::Extra1; break; - case 9: event.mouseButton.button = Mouse::Button::Extra2; break; + case Button1: event.button = Mouse::Button::Left; break; + case Button2: event.button = Mouse::Button::Middle; break; + case Button3: event.button = Mouse::Button::Right; break; + case 8: event.button = Mouse::Button::Extra1; break; + case 9: event.button = Mouse::Button::Extra2; break; } // clang-format on @@ -1951,49 +1927,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::Button::Left; + event.button = Mouse::Button::Left; break; case Button2: - event.mouseButton.button = Mouse::Button::Middle; + event.button = Mouse::Button::Middle; break; case Button3: - event.mouseButton.button = Mouse::Button::Right; + event.button = Mouse::Button::Right; break; case 8: - event.mouseButton.button = Mouse::Button::Extra1; + event.button = Mouse::Button::Extra1; break; case 9: - event.mouseButton.button = Mouse::Button::Extra2; + event.button = Mouse::Button::Extra2; break; } pushEvent(event); } else if ((button == Button4) || (button == Button5)) { - Event event; - - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::Wheel::Vertical; - 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::Wheel::Vertical; + 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::Wheel::Horizontal; - 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::Wheel::Horizontal; + event.delta = (button == 6) ? 1 : -1; + event.position = {windowEvent.xbutton.x, windowEvent.xbutton.y}; pushEvent(event); } break; @@ -2002,11 +1971,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; } @@ -2014,11 +1979,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; } @@ -2026,11 +1987,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 9acf84af19..059b39dbab 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -734,9 +734,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; } @@ -750,11 +748,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); @@ -782,11 +776,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 @@ -825,9 +815,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::FocusGained{}); break; } @@ -837,9 +825,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::FocusLost{}); break; } @@ -869,10 +855,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; @@ -884,14 +867,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; @@ -901,14 +883,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; } @@ -924,13 +905,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::Wheel::Vertical; - event.mouseWheelScroll.delta = static_cast(delta) / 120.f; - event.mouseWheelScroll.x = position.x; - event.mouseWheelScroll.y = position.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::Wheel::Vertical; + event.delta = static_cast(delta) / 120.f; + event.position = {position.x, position.y}; pushEvent(event); break; } @@ -946,12 +924,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::Wheel::Horizontal; - event.mouseWheelScroll.delta = -static_cast(delta) / 120.f; - event.mouseWheelScroll.x = position.x; - event.mouseWheelScroll.y = position.y; + Event::MouseWheelScrolled event; + event.wheel = Mouse::Wheel::Horizontal; + event.delta = -static_cast(delta) / 120.f; + event.position = {position.x, position.y}; pushEvent(event); break; } @@ -959,11 +935,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::Button::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Button::Left; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -971,11 +945,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::Button::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Button::Left; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -983,11 +955,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::Button::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Button::Right; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -995,11 +965,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::Button::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Button::Right; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1007,11 +975,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::Button::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = Mouse::Button::Middle; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1019,11 +985,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::Button::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = Mouse::Button::Middle; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1031,11 +995,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::Button::Extra1 : Mouse::Button::Extra2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonPressed event; + event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::Button::Extra1 : Mouse::Button::Extra2; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1043,11 +1005,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::Button::Extra1 : Mouse::Button::Extra2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); + Event::MouseButtonReleased event; + event.button = HIWORD(wParam) == XBUTTON1 ? Mouse::Button::Extra1 : Mouse::Button::Extra2; + event.position = {static_cast(LOWORD(lParam)), static_cast(HIWORD(lParam))}; pushEvent(event); break; } @@ -1061,9 +1021,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; } @@ -1104,9 +1062,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 @@ -1120,18 +1076,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 c7e30cb3d3..b068c7b1b4 100644 --- a/src/SFML/Window/WindowBase.cpp +++ b/src/SFML/Window/WindowBase.cpp @@ -409,10 +409,10 @@ void WindowBase::create(VideoMode mode, std::uint32_t& style, State& state) void 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 ffaccd2bea..e7496ed002 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -238,10 +238,10 @@ void WindowImpl::processJoystickEvents() const bool connected = m_joystickStatesImpl->states[i].connected; if (previousState.connected ^ connected) { - Event event; - event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected; - event.joystickButton.joystickId = i; - pushEvent(event); + if (connected) + pushEvent(Event::JoystickConnected{i}); + else + pushEvent(Event::JoystickDisconnected{i}); // Clear previous axes positions if (connected) @@ -262,13 +262,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; } } @@ -282,11 +276,10 @@ void WindowImpl::processJoystickEvents() if (prevPressed ^ currPressed) { - Event event; - event.type = currPressed ? Event::JoystickButtonPressed : Event::JoystickButtonReleased; - event.joystickButton.joystickId = i; - event.joystickButton.button = j; - pushEvent(event); + if (currPressed) + pushEvent(Event::JoystickButtonPressed{i, j}); + else + pushEvent(Event::JoystickButtonReleased{i, j}); } } } @@ -313,15 +306,7 @@ void WindowImpl::processSensorEvents() // If the value has changed, trigger an event if (m_sensorValue[sensor] != previousValue) // TODO use a threshold? - { - Event event; - event.type = Event::SensorChanged; - event.sensor.type = sensor; - event.sensor.x = m_sensorValue[sensor].x; - event.sensor.y = m_sensorValue[sensor].y; - event.sensor.z = m_sensorValue[sensor].z; - pushEvent(event); - } + pushEvent(Event::SensorChanged{sensor, m_sensorValue[sensor]}); } } } diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm index fec8f75b64..d05dc02324 100644 --- a/src/SFML/Window/iOS/SFAppDelegate.mm +++ b/src/SFML/Window/iOS/SFAppDelegate.mm @@ -119,13 +119,9 @@ - (void)applicationWillResignActive:(UIApplication*)application // - the application is sent to background // - the application is interrupted by a call or message - // Generate a LostFocus event + // Generate a FocusLost event if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::LostFocus; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::FocusLost{}); } @@ -143,13 +139,9 @@ - (void)applicationDidBecomeActive:(UIApplication*)application // - the application is sent to foreground // - the application was interrupted by a call or message - // Generate a GainedFocus event + // Generate a FocusGained event if (self.sfWindow) - { - sf::Event event; - event.type = sf::Event::GainedFocus; - sfWindow->forwardEvent(event); - } + sfWindow->forwardEvent(sf::Event::FocusGained{}); } @@ -165,11 +157,7 @@ - (void)applicationWillTerminate:(UIApplication*)application { // 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 @@ - (void)deviceOrientationDidChange:(NSNotification*)notification 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 @@ - (void)notifyTouchBegin:(unsigned int)index atPosition:(sf::Vector2i)position // 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 @@ - (void)notifyTouchMove:(unsigned int)index atPosition:(sf::Vector2i)position // 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 @@ - (void)notifyTouchEnd:(unsigned int)index atPosition:(sf::Vector2i)position // 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 @@ - (void)notifyTouchEnd:(unsigned int)index atPosition:(sf::Vector2i)position - (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 871e3fa0c7..83362b7f72 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.mm +++ b/src/SFML/Window/iOS/WindowImplUIKit.mm @@ -230,9 +230,9 @@ //////////////////////////////////////////////////////////// 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 fd7bb1fa1b..c11859dfbf 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 546be93548..13fc7d359c 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 716fd39448..5f68f8e73f 100644 --- a/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm +++ b/src/SFML/Window/macOS/SFOpenGLView+keyboard.mm @@ -84,7 +84,7 @@ - (void)keyDown:(NSEvent*)theEvent // 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::Key::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown)) m_requester->keyDown(key); @@ -156,7 +156,7 @@ - (void)sfKeyUp:(NSEvent*)theEvent 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::Key::Unknown) || (key.scancode != sf::Keyboard::Scan::Unknown)) m_requester->keyUp(key); @@ -178,7 +178,7 @@ - (void)flagsChanged:(NSEvent*)theEvent //////////////////////////////////////////////////////// -+ (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 e0ec1a11b4..e71ba577fa 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::Key::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/SFOpenGLView+mouse.mm b/src/SFML/Window/macOS/SFOpenGLView+mouse.mm index 3a42bc2f68..0055d49f73 100644 --- a/src/SFML/Window/macOS/SFOpenGLView+mouse.mm +++ b/src/SFML/Window/macOS/SFOpenGLView+mouse.mm @@ -138,7 +138,7 @@ - (void)handleMouseDown:(NSEvent*)theEvent NSPoint loc = [self cursorPositionFromEvent:theEvent]; if (button) - m_requester->mouseDownAt(*button, static_cast(loc.x), static_cast(loc.y)); + m_requester->mouseDownAt(*button, sf::Vector2i(sf::Vector2(loc.x, loc.y))); } } @@ -183,7 +183,7 @@ - (void)handleMouseUp:(NSEvent*)theEvent NSPoint loc = [self cursorPositionFromEvent:theEvent]; if (button) - m_requester->mouseUpAt(*button, static_cast(loc.x), static_cast(loc.y)); + m_requester->mouseUpAt(*button, sf::Vector2i(sf::Vector2(loc.x, loc.y))); } } @@ -244,7 +244,7 @@ - (void)handleMouseMove:(NSEvent*)theEvent // when the mouse is dragged. That would be too easy!) [self updateMouseState]; if ((m_requester != nil) && m_mouseIsIn) - m_requester->mouseMovedAt(static_cast(loc.x), static_cast(loc.y)); + m_requester->mouseMovedAt(sf::Vector2i(sf::Vector2(loc.x, loc.y))); } @@ -304,8 +304,7 @@ - (void)scrollWheel:(NSEvent*)theEvent NSPoint loc = [self cursorPositionFromEvent:theEvent]; m_requester->mouseWheelScrolledAt(static_cast([theEvent deltaX]), static_cast([theEvent deltaY]), - static_cast(loc.x), - static_cast(loc.y)); + sf::Vector2i(sf::Vector2(loc.x, loc.y))); } // Transmit to non-SFML responder diff --git a/src/SFML/Window/macOS/SFOpenGLView.mm b/src/SFML/Window/macOS/SFOpenGLView.mm index c80552c43a..deb2aaa2c3 100644 --- a/src/SFML/Window/macOS/SFOpenGLView.mm +++ b/src/SFML/Window/macOS/SFOpenGLView.mm @@ -289,7 +289,7 @@ - (void)windowDidBecomeKey:(NSNotification*)notification [self updateCursorGrabbed]; if (m_requester) - m_requester->windowGainedFocus(); + m_requester->windowFocusGained(); if (m_fullscreen) [self enterFullscreen]; @@ -304,7 +304,7 @@ - (void)windowDidResignKey:(NSNotification*)notification [self updateCursorGrabbed]; if (m_requester) - m_requester->windowLostFocus(); + m_requester->windowFocusLost(); if (m_fullscreen) [self exitFullscreen]; diff --git a/src/SFML/Window/macOS/Scaling.h b/src/SFML/Window/macOS/Scaling.h index df4102599c..0d9c97a2a8 100644 --- a/src/SFML/Window/macOS/Scaling.h +++ b/src/SFML/Window/macOS/Scaling.h @@ -75,13 +75,6 @@ void scaleOut(T& out, id delegate) out *= static_cast(delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor()); } -template -void scaleOutWidthHeight(T& width, T& height, id delegate) -{ - scaleOut(width, delegate); - scaleOut(height, delegate); -} - template void scaleOutXY(T& out, id delegate) { diff --git a/src/SFML/Window/macOS/WindowImplCocoa.hpp b/src/SFML/Window/macOS/WindowImplCocoa.hpp index 9a42ff3a2e..8ac0076341 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.hpp +++ b/src/SFML/Window/macOS/WindowImplCocoa.hpp @@ -110,7 +110,7 @@ class WindowImplCocoa : public WindowImpl /// \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 @@ -118,7 +118,7 @@ class WindowImplCocoa : public WindowImpl /// Send the event to SFML WindowImpl class. /// //////////////////////////////////////////////////////////// - void windowLostFocus(); + void windowFocusLost(); //////////////////////////////////////////////////////////// /// \brief Window Get Focus Event - called by the cocoa window object @@ -126,55 +126,51 @@ class WindowImplCocoa : public WindowImpl /// Send the event to SFML WindowImpl class. /// //////////////////////////////////////////////////////////// - void windowGainedFocus(); + void windowFocusGained(); //////////////////////////////////////////////////////////// /// \brief Mouse Down Event - called by the cocoa view object /// /// Send the event to SFML WindowImpl class. /// - /// \param button active button - /// \param x mouse x position - /// \param y mouse y position + /// \param button active button + /// \param position mouse x and y position /// //////////////////////////////////////////////////////////// - void mouseDownAt(Mouse::Button button, int x, int y); + void mouseDownAt(Mouse::Button button, Vector2i position); //////////////////////////////////////////////////////////// /// \brief Mouse Up Event - called by the cocoa view object /// /// Send the event to SFML WindowImpl class. /// - /// \param button active button - /// \param x mouse x position - /// \param y mouse y position + /// \param button active button + /// \param position mouse x and y position /// //////////////////////////////////////////////////////////// - void mouseUpAt(Mouse::Button button, int x, int y); + void mouseUpAt(Mouse::Button button, Vector2i position); //////////////////////////////////////////////////////////// /// \brief Mouse Moved Event - called by the cocoa view object /// /// Send the event to SFML WindowImpl class. /// - /// \param x mouse x position - /// \param y mouse y position + /// \param position mouse x and y position /// //////////////////////////////////////////////////////////// - void mouseMovedAt(int x, int y); + void mouseMovedAt(Vector2i position); //////////////////////////////////////////////////////////// /// \brief Mouse Wheel Scrolled Event - called by the cocoa view object /// /// Send the event to SFML WindowImpl class. /// - /// \param deltaX horizontal scrolling delta - /// \param deltaY vertical scrolling delta - /// \param x mouse x position - /// \param y mouse y position + /// \param deltaX horizontal scrolling delta + /// \param deltaY vertical scrolling delta + /// \param position mouse x and y position /// //////////////////////////////////////////////////////////// - void mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y); + void mouseWheelScrolledAt(float deltaX, float deltaY, Vector2i position); //////////////////////////////////////////////////////////// /// \brief Mouse In Event - called by the cocoa view object @@ -197,20 +193,20 @@ class WindowImplCocoa : public WindowImpl /// /// 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 8220b50472..09d21bdbeb 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.mm +++ b/src/SFML/Window/macOS/WindowImplCocoa.mm @@ -217,49 +217,33 @@ void showMouseCursor() //////////////////////////////////////////////////////////// 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}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::windowLostFocus() +void WindowImplCocoa::windowFocusLost() { if (!m_showCursor && [m_delegate isMouseInside]) showMouseCursor(); // Make sure the cursor is visible - - Event event; - event.type = Event::LostFocus; - - pushEvent(event); + pushEvent(Event::FocusLost{}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::windowGainedFocus() +void WindowImplCocoa::windowFocusGained() { if (!m_showCursor && [m_delegate isMouseInside]) hideMouseCursor(); // Restore user's setting - - Event event; - event.type = Event::GainedFocus; - - pushEvent(event); + pushEvent(Event::FocusGained{}); } #pragma mark @@ -267,65 +251,34 @@ void showMouseCursor() //////////////////////////////////////////////////////////// -void WindowImplCocoa::mouseDownAt(Mouse::Button button, int x, int y) +void WindowImplCocoa::mouseDownAt(Mouse::Button button, Vector2i position) { - 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); + scaleOutXY(position, m_delegate); + pushEvent(Event::MouseButtonPressed{button, position}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::mouseUpAt(Mouse::Button button, int x, int y) +void WindowImplCocoa::mouseUpAt(Mouse::Button button, Vector2i position) { - 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); + scaleOutXY(position, m_delegate); + pushEvent(Event::MouseButtonReleased{button, position}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::mouseMovedAt(int x, int y) +void WindowImplCocoa::mouseMovedAt(Vector2i position) { - Event event; - event.type = Event::MouseMoved; - event.mouseMove.x = x; - event.mouseMove.y = y; - scaleOutXY(event.mouseMove, m_delegate); - - pushEvent(event); + scaleOutXY(position, m_delegate); + pushEvent(Event::MouseMoved{position}); } //////////////////////////////////////////////////////////// -void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, int x, int y) +void WindowImplCocoa::mouseWheelScrolledAt(float deltaX, float deltaY, Vector2i position) { - Event event; - - event.type = Event::MouseWheelScrolled; - event.mouseWheelScroll.wheel = Mouse::Wheel::Vertical; - 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::Wheel::Horizontal; - event.mouseWheelScroll.delta = deltaX; - event.mouseWheelScroll.x = x; - event.mouseWheelScroll.y = y; - scaleOutXY(event.mouseWheelScroll, m_delegate); - pushEvent(event); + scaleOutXY(position, m_delegate); + pushEvent(Event::MouseWheelScrolled{Mouse::Wheel::Vertical, deltaY, position}); + pushEvent(Event::MouseWheelScrolled{Mouse::Wheel::Horizontal, deltaX, position}); } //////////////////////////////////////////////////////////// @@ -333,11 +286,7 @@ void showMouseCursor() { if (!m_showCursor) hideMouseCursor(); // Restore user's setting - - Event event; - event.type = Event::MouseEntered; - - pushEvent(event); + pushEvent(Event::MouseEntered{}); } //////////////////////////////////////////////////////////// @@ -345,11 +294,7 @@ void showMouseCursor() { if (!m_showCursor) showMouseCursor(); // Make sure the cursor is visible - - Event event; - event.type = Event::MouseLeft; - - pushEvent(event); + pushEvent(Event::MouseLeft{}); } @@ -358,23 +303,15 @@ void showMouseCursor() //////////////////////////////////////////////////////////// -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); } @@ -382,11 +319,7 @@ void showMouseCursor() //////////////////////////////////////////////////////////// void WindowImplCocoa::textEntered(unichar charcode) { - Event event; - event.type = Event::TextEntered; - event.text.unicode = charcode; - - pushEvent(event); + pushEvent(Event::TextEntered{charcode}); } diff --git a/src/SFML/Window/macOS/WindowImplDelegateProtocol.h b/src/SFML/Window/macOS/WindowImplDelegateProtocol.h index 5566896c52..a35efc0d78 100644 --- a/src/SFML/Window/macOS/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/macOS/WindowImplDelegateProtocol.h @@ -60,7 +60,7 @@ class WindowImplCocoa; /// The requester is a WindowImplCocoa. It's used to send back /// event via these functions: /// -/// windowClosed, windowResized, windowLostFocus, windowGainedFocus +/// windowClosed, windowResized, windowFocusLost, windowFocusGained /// /// mouseDownAt, mouseUpAt, mouseMovedAt, mouseWheelScrolledAt, /// mouseMovedIn, mouseMovedOut diff --git a/test/Window/Event.test.cpp b/test/Window/Event.test.cpp index 1fbf65a392..99126ca903 100644 --- a/test/Window/Event.test.cpp +++ b/test/Window/Event.test.cpp @@ -16,7 +16,253 @@ 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.is()); + CHECK(event.getIf()); + } + + SECTION("Template constructor") + { + const sf::Event event = sf::Event::Resized{{1, 2}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& resized = *event.getIf(); + CHECK(resized.size == sf::Vector2u(1, 2)); + } + } + + SECTION("Assign all possible values") + { + sf::Event event; + event = sf::Event::Closed{}; + CHECK(event.is()); + CHECK(event.getIf()); + + event = sf::Event::Resized{{1, 2}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& resized = *event.getIf(); + CHECK(resized.size == sf::Vector2u(1, 2)); + + event = sf::Event::FocusLost{}; + CHECK(event.is()); + CHECK(event.getIf()); + + event = sf::Event::FocusGained{}; + CHECK(event.is()); + CHECK(event.getIf()); + + event = sf::Event::TextEntered{123456}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& textEntered = *event.getIf(); + CHECK(textEntered.unicode == 123456); + + event = sf::Event::KeyPressed{sf::Keyboard::Key::C, sf::Keyboard::Scan::C, true, true, true, true}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& keyPressed = *event.getIf(); + CHECK(keyPressed.code == sf::Keyboard::Key::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::Key::D, sf::Keyboard::Scan::D, true, true, true, true}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& keyReleased = *event.getIf(); + CHECK(keyReleased.code == sf::Keyboard::Key::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::Wheel::Horizontal, 3.14f, {4, 5}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& mouseWheelScrolled = *event.getIf(); + CHECK(mouseWheelScrolled.wheel == sf::Mouse::Wheel::Horizontal); + CHECK(mouseWheelScrolled.delta == 3.14f); + CHECK(mouseWheelScrolled.position == sf::Vector2i(4, 5)); + + event = sf::Event::MouseButtonPressed{sf::Mouse::Button::Middle, {6, 7}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& mouseButtonPressed = *event.getIf(); + CHECK(mouseButtonPressed.button == sf::Mouse::Button::Middle); + CHECK(mouseButtonPressed.position == sf::Vector2i(6, 7)); + + event = sf::Event::MouseButtonReleased{sf::Mouse::Button::Extra1, {8, 9}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& mouseButtonReleased = *event.getIf(); + CHECK(mouseButtonReleased.button == sf::Mouse::Button::Extra1); + CHECK(mouseButtonReleased.position == sf::Vector2i(8, 9)); + + event = sf::Event::MouseMoved{{4, 2}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& mouseMoved = *event.getIf(); + CHECK(mouseMoved.position == sf::Vector2i(4, 2)); + + event = sf::Event::MouseEntered{}; + CHECK(event.is()); + CHECK(event.getIf()); + + event = sf::Event::MouseLeft{}; + CHECK(event.is()); + CHECK(event.getIf()); + + event = sf::Event::JoystickButtonPressed{100, 200}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& joystickButtonPressed = *event.getIf(); + CHECK(joystickButtonPressed.joystickId == 100); + CHECK(joystickButtonPressed.button == 200); + + event = sf::Event::JoystickButtonReleased{300, 400}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& joystickButtonReleased = *event.getIf(); + CHECK(joystickButtonReleased.joystickId == 300); + CHECK(joystickButtonReleased.button == 400); + + event = sf::Event::JoystickMoved{300, sf::Joystick::Axis::Z, 1.23f}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& joystickMoved = *event.getIf(); + 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.getIf()); + const auto& joystickConnected = *event.getIf(); + CHECK(joystickConnected.joystickId == 42); + + event = sf::Event::JoystickDisconnected{43}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& joystickDisconnected = *event.getIf(); + CHECK(joystickDisconnected.joystickId == 43); + + event = sf::Event::TouchBegan{99, {98, 97}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& touchBegan = *event.getIf(); + CHECK(touchBegan.finger == 99); + CHECK(touchBegan.position == sf::Vector2i(98, 97)); + + event = sf::Event::TouchMoved{96, {95, 94}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& touchMoved = *event.getIf(); + CHECK(touchMoved.finger == 96); + CHECK(touchMoved.position == sf::Vector2i(95, 94)); + + event = sf::Event::TouchEnded{93, {92, 91}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& touchEnded = *event.getIf(); + CHECK(touchEnded.finger == 93); + CHECK(touchEnded.position == sf::Vector2i(92, 91)); + + event = sf::Event::SensorChanged{sf::Sensor::Type::Gravity, {1.2f, 3.4f, 5.6f}}; + CHECK(event.is()); + CHECK(event.getIf()); + const auto& sensorChanged = *event.getIf(); + 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 dc5b91663e..fac3c5c4cd 100644 --- a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp @@ -67,13 +67,14 @@ 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::Key::Escape) + if (const auto* keyPressed = event.getIf(); + keyPressed && keyPressed->code == sf::Keyboard::Key::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 d4a6e1918f..e3db2187f7 100644 --- a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp @@ -65,13 +65,14 @@ 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::Key::Escape) + if (const auto* keyPressed = event.getIf(); + keyPressed && keyPressed->code == sf::Keyboard::Key::Escape) { window.close(); }