//////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library // Copyright (C) 2007-2025 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. // //////////////////////////////////////////////////////////// #pragma once //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include #include #include #include #include #include #include namespace sf { //////////////////////////////////////////////////////////// /// \brief Defines a system event and its parameters /// //////////////////////////////////////////////////////////// class Event { public: //////////////////////////////////////////////////////////// /// \brief Closed event subtype /// //////////////////////////////////////////////////////////// struct Closed { }; //////////////////////////////////////////////////////////// /// \brief Resized event subtype /// //////////////////////////////////////////////////////////// struct Resized { Vector2u size; //!< New size, in pixels }; //////////////////////////////////////////////////////////// /// \brief Lost focus event subtype /// //////////////////////////////////////////////////////////// struct FocusLost { }; //////////////////////////////////////////////////////////// /// \brief Gained focus event subtype /// //////////////////////////////////////////////////////////// struct FocusGained { }; //////////////////////////////////////////////////////////// /// \brief Text event subtype /// //////////////////////////////////////////////////////////// struct TextEntered { char32_t unicode{}; //!< UTF-32 Unicode value of the character }; //////////////////////////////////////////////////////////// /// \brief Key pressed event subtype /// //////////////////////////////////////////////////////////// struct KeyPressed { 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 Key released event subtype /// //////////////////////////////////////////////////////////// struct KeyReleased { Keyboard::Key code{}; //!< Code of the key that has been released Keyboard::Scancode scancode{}; //!< Physical code of the key that has been released 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 Mouse wheel scrolled event subtype /// //////////////////////////////////////////////////////////// struct MouseWheelScrolled { 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 Mouse button pressed event subtype /// //////////////////////////////////////////////////////////// struct MouseButtonPressed { 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 }; //////////////////////////////////////////////////////////// /// \brief Mouse button released event subtype /// //////////////////////////////////////////////////////////// struct MouseButtonReleased { Mouse::Button button{}; //!< Code of the button that has been released Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// /// \brief Mouse move event subtype /// //////////////////////////////////////////////////////////// struct MouseMoved { Vector2i position; //!< Position of the mouse pointer, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// /// \brief Mouse move raw event subtype /// /// Raw mouse input data comes unprocessed from the /// operating system hence "raw". While the MouseMoved /// position value is dependent on the screen resolution, /// raw data is not. If the physical mouse is moved too /// little to cause the screen cursor to move at least a /// single pixel, no MouseMoved event will be generated. In /// contrast, any movement information generated by the /// mouse independent of its sensor resolution will always /// generate a `MouseMovedRaw` event. /// /// In addition to screen resolution independence, raw /// mouse data also does not have mouse acceleration or /// smoothing applied to it as MouseMoved does. /// /// Raw mouse movement data is intended for controlling /// non-cursor movement, e.g. controlling the camera /// orientation in a first person view, whereas MouseMoved /// is intended primarily for controlling things related to /// the screen cursor hence the additional processing /// applied to it. /// /// Currently, raw mouse input events will only be generated /// on Windows and Linux. /// //////////////////////////////////////////////////////////// struct MouseMovedRaw { Vector2i delta; ///< Delta movement of the mouse since the last event }; //////////////////////////////////////////////////////////// /// \brief Mouse entered event subtype /// //////////////////////////////////////////////////////////// struct MouseEntered { }; //////////////////////////////////////////////////////////// /// \brief Mouse left event subtype /// //////////////////////////////////////////////////////////// struct MouseLeft { }; //////////////////////////////////////////////////////////// /// \brief Joystick button pressed event subtype /// //////////////////////////////////////////////////////////// struct JoystickButtonPressed { 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 Joystick button released event subtype /// //////////////////////////////////////////////////////////// struct JoystickButtonReleased { unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1]) unsigned int button{}; //!< Index of the button that has been released (in range [0 .. Joystick::ButtonCount - 1]) }; //////////////////////////////////////////////////////////// /// \brief Joystick axis move event subtype /// //////////////////////////////////////////////////////////// struct JoystickMoved { unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1]) Joystick::Axis axis{}; //!< Axis on which the joystick moved float position{}; //!< New position on the axis (in range [-100 .. 100]) }; //////////////////////////////////////////////////////////// /// \brief Joystick connected event subtype /// //////////////////////////////////////////////////////////// struct JoystickConnected { unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1]) }; //////////////////////////////////////////////////////////// /// \brief Joystick disconnected event subtype /// //////////////////////////////////////////////////////////// struct JoystickDisconnected { unsigned int joystickId{}; //!< Index of the joystick (in range [0 .. Joystick::Count - 1]) }; //////////////////////////////////////////////////////////// /// \brief Touch began event subtype /// //////////////////////////////////////////////////////////// struct TouchBegan { unsigned int finger{}; //!< Index of the finger in case of multi-touch events Vector2i position; //!< Start position of the touch, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// /// \brief Touch moved event subtype /// //////////////////////////////////////////////////////////// struct TouchMoved { unsigned int finger{}; //!< Index of the finger in case of multi-touch events Vector2i position; //!< Current position of the touch, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// /// \brief Touch ended event subtype /// //////////////////////////////////////////////////////////// struct TouchEnded { unsigned int finger{}; //!< Index of the finger in case of multi-touch events Vector2i position; //!< Final position of the touch, relative to the top left of the owner window }; //////////////////////////////////////////////////////////// /// \brief Sensor event subtype /// //////////////////////////////////////////////////////////// struct SensorChanged { Sensor::Type type{}; //!< Type of the sensor Vector3f value; //!< Current value of the sensor on the X, Y, and Z axes }; //////////////////////////////////////////////////////////// /// \brief Construct from a given `sf::Event` subtype /// /// \tparam `TEventSubtype` Type of event subtype used to construct the event /// /// \param eventSubtype Event subtype instance used to construct the event /// //////////////////////////////////////////////////////////// template Event(const TEventSubtype& eventSubtype); //////////////////////////////////////////////////////////// /// \brief Check current event subtype /// /// \tparam `TEventSubtype` Type of the event subtype to check against /// /// \return `true` if the current event subtype matches given template parameter /// //////////////////////////////////////////////////////////// template [[nodiscard]] bool is() const; //////////////////////////////////////////////////////////// /// \brief Attempt to get specified event subtype /// /// \tparam `TEventSubtype` Type of the desired event subtype /// /// \return Address of current event subtype, otherwise `nullptr` /// //////////////////////////////////////////////////////////// template [[nodiscard]] const TEventSubtype* getIf() const; //////////////////////////////////////////////////////////// /// \brief Apply a visitor to the event /// /// \param visitor The visitor to apply /// /// \return The result of applying the visitor to the event /// //////////////////////////////////////////////////////////// template decltype(auto) visit(Visitor&& visitor) const; private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// std::variant m_data; //!< Event data //////////////////////////////////////////////////////////// // Helper functions //////////////////////////////////////////////////////////// template [[nodiscard]] static constexpr bool isInParameterPack(const std::variant*) { return std::disjunction_v...>; } template static constexpr bool isEventSubtype = isInParameterPack(decltype (&m_data)(nullptr)); friend class WindowBase; template [[nodiscard]] static constexpr bool isInvocableWithEventSubtype(const std::variant*) { return std::disjunction_v...>; } template static constexpr bool isEventHandler = isInvocableWithEventSubtype(decltype (&m_data)(nullptr)); }; } // namespace sf #include //////////////////////////////////////////////////////////// /// \class sf::Event /// \ingroup window /// /// `sf::Event` holds all the information about a system event /// that just happened. Events are retrieved using the /// `sf::Window::pollEvent` and `sf::Window::waitEvent` functions. /// /// A `sf::Event` instance contains the subtype of the event /// (mouse moved, key pressed, window closed, ...) as well /// as the details about this particular event. Each event /// corresponds to a different subtype struct which contains /// the data required to process that event. /// /// Event subtypes are event types belonging to `sf::Event`, /// such as `sf::Event::Closed` or `sf::Event::MouseMoved`. /// /// The way to access the current active event subtype is via /// `sf::Event::getIf`. This member function returns the address /// of the event subtype struct if the event subtype matches the /// active event, otherwise it returns `nullptr`. /// /// `sf::Event::is` is used to check the active event subtype /// without actually reading any of the corresponding event data. /// /// \code /// while (const std::optional event = window.pollEvent()) /// { /// // Window closed or escape key pressed: exit /// if (event->is() || /// (event->is() && /// event->getIf()->code == sf::Keyboard::Key::Escape)) /// window.close(); /// /// // The window was resized /// if (const auto* resized = event->getIf()) /// doSomethingWithTheNewSize(resized->size); /// /// // etc ... /// } /// \endcode /// ////////////////////////////////////////////////////////////