Skip to content

Commit

Permalink
Ignore SDL events that were generated on another window
Browse files Browse the repository at this point in the history
  • Loading branch information
texus committed Nov 6, 2024
1 parent 842ef89 commit d60c5bb
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 4 deletions.
2 changes: 1 addition & 1 deletion include/TGUI/Backend/Window/Backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ TGUI_MODULE_EXPORT namespace tgui
///
/// @return Whether queries modifier key is being pressed
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TGUI_DEPRECATED("Use gui.isKeyboardModifierPressed(modifierKey) instead") TGUI_NODISCARD virtual bool isKeyboardModifierPressed(Event::KeyModifier modifierKey) = 0;
TGUI_DEPRECATED("Use gui.isKeyboardModifierPressed(modifierKey) instead") TGUI_NODISCARD virtual bool isKeyboardModifierPressed(Event::KeyModifier modifierKey);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Changes the contents of the clipboard
Expand Down
2 changes: 1 addition & 1 deletion include/TGUI/Layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ TGUI_MODULE_EXPORT namespace tgui
Right, //!< Places the widget on the right side and sets its height to the area between Top and Bottom aligned components. Width needs to be manually set.
Bottom, //!< Places the widget on on the bottom and sets its width to the area between Leftmost and Rightmost aligned components. Height needs to be manually set.
Leftmost, //!< Places the widget on the left side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no widget uses Top or Bottom alignment.
Rightmost, //!< Places the widget on the right side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no widget uses Top or Bottom alignment.
Rightmost, //!< Places the widget on the right side and sets height to 100%. Width needs to be manually set. Same as Right alignment if no widget uses Top or Bottom alignment.
Fill //!< Sets the position and size to fill the entire area that isn't already taken by components with the other AutoLayout values.
};

Expand Down
4 changes: 2 additions & 2 deletions include/TGUI/TextStyle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

TGUI_MODULE_EXPORT namespace tgui
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Enumeration of the text drawing styles
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
enum TextStyle : unsigned int
{
Regular = 0, //!< Regular characters, no style
Expand Down
2 changes: 2 additions & 0 deletions include/TGUI/Widgets/ClickableWidget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ TGUI_MODULE_EXPORT namespace tgui
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Clickable widget
///
/// The widget acts as an invisible clickable area. It is also used as a base class for other widgets that are clickable.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class TGUI_API ClickableWidget : public Widget
{
Expand Down
8 changes: 8 additions & 0 deletions src/Backend/Window/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ namespace tgui
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool Backend::isKeyboardModifierPressed(Event::KeyModifier)
{
// All backends must either override this function or the one inside the gui class.
return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Backend::setClipboard(const String& contents)
{
m_clipboardContents = contents;
Expand Down
51 changes: 51 additions & 0 deletions src/Backend/Window/SDL/BackendGuiSDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,43 @@ namespace tgui

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if SDL_MAJOR_VERSION < 3
static std::uint32_t getWindowIdFromEvent(const SDL_Event& eventSDL)
{
switch (eventSDL.type)
{
case SDL_WINDOWEVENT:
return eventSDL.window.windowID;

case SDL_EVENT_TEXT_INPUT:
return eventSDL.text.windowID;

case SDL_EVENT_KEY_DOWN:
return eventSDL.key.windowID;

case SDL_EVENT_MOUSE_WHEEL:
return eventSDL.wheel.windowID;

case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
return eventSDL.button.windowID;

case SDL_EVENT_MOUSE_MOTION:
return eventSDL.motion.windowID;

case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
case SDL_EVENT_FINGER_MOTION:
return eventSDL.tfinger.windowID;

default:
return 0;
}
}
#endif

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool BackendGuiSDL::convertEvent(const SDL_Event& eventSDL, Event& eventTGUI)
{
switch (eventSDL.type)
Expand Down Expand Up @@ -460,6 +497,20 @@ namespace tgui

bool BackendGuiSDL::handleEvent(const SDL_Event& sdlEvent)
{
// Ignore events from a window other than the one used by the gui.
// Not all events are related to a window, and manually crafted events will also not have a valid window id,
// so if the event has no associated window then we will also process it.
#if SDL_MAJOR_VERSION >= 3
SDL_Window* window = SDL_GetWindowFromEvent(&sdlEvent);
if (window && (window != m_window))
return false;
#else
const std::uint32_t eventWindowId = getWindowIdFromEvent(sdlEvent);
const std::uint32_t windowId = SDL_GetWindowID(m_window);
if ((eventWindowId != 0) && (windowId != 0) && (eventWindowId != windowId))
return false;
#endif

// Detect scrolling with two fingers by examining touch events
if ((sdlEvent.type == SDL_EVENT_FINGER_DOWN) || (sdlEvent.type == SDL_EVENT_FINGER_UP) || (sdlEvent.type == SDL_EVENT_FINGER_MOTION))
{
Expand Down
22 changes: 22 additions & 0 deletions tests/BackendEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ TEST_CASE("[Backend events]")
eventSDL.type = SDL_WINDOWEVENT;
eventSDL.window.event = SDL_WINDOWEVENT_FOCUS_GAINED;
#endif
eventSDL.window.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand All @@ -1220,6 +1221,7 @@ TEST_CASE("[Backend events]")
eventSDL.type = SDL_WINDOWEVENT;
eventSDL.window.event = SDL_WINDOWEVENT_FOCUS_LOST;
#endif
eventSDL.window.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand Down Expand Up @@ -1247,6 +1249,7 @@ TEST_CASE("[Backend events]")
#endif
eventSDL.window.data1 = 400;
eventSDL.window.data2 = 300;
eventSDL.window.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand All @@ -1259,6 +1262,7 @@ TEST_CASE("[Backend events]")
{
SDL_Event eventSDL;
eventSDL.type = SDL_EVENT_TEXT_INPUT;
eventSDL.text.windowID = 0;
#if SDL_MAJOR_VERSION >= 3
char textInput[4] = {
static_cast<char>(static_cast<unsigned char>(0xE2)),
Expand Down Expand Up @@ -1295,10 +1299,12 @@ TEST_CASE("[Backend events]")
eventSDL.motion.which = 1;
eventSDL.motion.x = 200;
eventSDL.motion.y = 150;
eventSDL.motion.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);
#endif

eventSDL.type = SDL_EVENT_MOUSE_WHEEL;
eventSDL.wheel.windowID = 0;
eventSDL.wheel.x = 0;
eventSDL.wheel.y = 2;
eventSDL.wheel.direction = SDL_MOUSEWHEEL_NORMAL;
Expand Down Expand Up @@ -1337,6 +1343,7 @@ TEST_CASE("[Backend events]")
eventSDL.button.button = SDL_BUTTON_LEFT;
eventSDL.button.x = 200;
eventSDL.button.y = 150;
eventSDL.button.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand Down Expand Up @@ -1366,6 +1373,7 @@ TEST_CASE("[Backend events]")
eventSDL.button.button = SDL_BUTTON_LEFT;
eventSDL.button.x = 200;
eventSDL.button.y = 150;
eventSDL.button.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand Down Expand Up @@ -1394,6 +1402,7 @@ TEST_CASE("[Backend events]")
eventSDL.motion.which = 1;
eventSDL.motion.x = 200;
eventSDL.motion.y = 150;
eventSDL.motion.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand All @@ -1420,6 +1429,7 @@ TEST_CASE("[Backend events]")
#endif
eventSDL.tfinger.x = 200.f / windowSize.x;
eventSDL.tfinger.y = 150.f / windowSize.y;
eventSDL.tfinger.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
Expand Down Expand Up @@ -1453,6 +1463,8 @@ TEST_CASE("[Backend events]")
eventSDL.type = SDL_WINDOWEVENT;
eventSDL.window.event = SDL_WINDOWEVENT_ENTER;
#endif
eventSDL.window.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
REQUIRE(eventTGUI.type == tgui::Event::Type::MouseEntered);
Expand All @@ -1467,6 +1479,8 @@ TEST_CASE("[Backend events]")
eventSDL.type = SDL_WINDOWEVENT;
eventSDL.window.event = SDL_WINDOWEVENT_LEAVE;
#endif
eventSDL.window.windowID = 0;

tgui::Event eventTGUI;
REQUIRE(backendGuiSDL->convertEvent(eventSDL, eventTGUI));
REQUIRE(eventTGUI.type == tgui::Event::Type::MouseLeft);
Expand Down Expand Up @@ -1500,6 +1514,7 @@ TEST_CASE("[Backend events]")
// Type 3 characters in the edit box
SDL_Event eventSDL;
eventSDL.type = SDL_EVENT_TEXT_INPUT;
eventSDL.text.windowID = 0;
#if SDL_MAJOR_VERSION >= 3
char textInput[2] = "A";
eventSDL.text.text = textInput;
Expand Down Expand Up @@ -1554,10 +1569,12 @@ TEST_CASE("[Backend events]")
eventSDL.motion.which = 1;
eventSDL.motion.x = 260;
eventSDL.motion.y = 80;
eventSDL.motion.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);
#endif
eventSDL.type = SDL_EVENT_MOUSE_WHEEL;
eventSDL.wheel.direction = SDL_MOUSEWHEEL_NORMAL;
eventSDL.wheel.windowID = 0;
eventSDL.wheel.x = 0;
eventSDL.wheel.y = 4;
#if (SDL_MAJOR_VERSION == 2) && ((SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 18))
Expand All @@ -1580,6 +1597,7 @@ TEST_CASE("[Backend events]")
eventSDL.motion.which = 1;
eventSDL.motion.x = 260;
eventSDL.motion.y = 80;
eventSDL.motion.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);
slider->onMouseLeave([&]{ genericCallback(mouseLeftCount); });
#if SDL_MAJOR_VERSION >= 3
Expand All @@ -1598,23 +1616,27 @@ TEST_CASE("[Backend events]")
eventSDL.button.button = SDL_BUTTON_LEFT;
eventSDL.button.x = 320;
eventSDL.button.y = 100;
eventSDL.button.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);
eventSDL.type = SDL_EVENT_MOUSE_MOTION;
eventSDL.motion.which = 1;
eventSDL.motion.x = 300;
eventSDL.motion.y = 105;
eventSDL.motion.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);
eventSDL.type = SDL_EVENT_MOUSE_BUTTON_UP;
eventSDL.button.which = 1;
eventSDL.button.button = SDL_BUTTON_LEFT;
eventSDL.button.x = 290;
eventSDL.button.y = 110;
eventSDL.button.windowID = 0;
backendGuiSDL->handleEvent(eventSDL);

// Resize the child window using touch events (decrease height with 10px)
// Note that the resizing ignores the position of the touch ended event
const tgui::Vector2f windowSize = backendGuiSDL->getViewport().getSize();
eventSDL.type = SDL_EVENT_FINGER_DOWN;
eventSDL.tfinger.windowID = 0;
#if SDL_MAJOR_VERSION >= 3
eventSDL.tfinger.touchID = 1;
#else
Expand Down

0 comments on commit d60c5bb

Please sign in to comment.