Skip to content

First-ever click into unfocused window causes mouse drag from {0,0} #338

@vid512

Description

@vid512

Attached is slightly edited dual window demo. It changes code so that primary window gets initial focus, and that secondary window places ImGui window over point {0,0}.

Now, when you click into secondary window for the first time (and hold the click longer than single frame), it behaves as if you clicked at {0,0} on the first frame, and then dragged the mouse to wherever you have actually clicked on the next frame.

According to my analysis, this is caused by following code in ImGui::SFML::Update

imgui-sfml/imgui-SFML.cpp

Lines 497 to 507 in ab6b5cf

if (!s_currWindowCtx->mouseMoved)
{
if (sf::Touch::isDown(0))
s_currWindowCtx->touchPos = sf::Touch::getPosition(0, window);
Update(s_currWindowCtx->touchPos, sf::Vector2f(target.getSize()), dt);
}
else
{
Update(sf::Mouse::getPosition(window), sf::Vector2f(target.getSize()), dt);
}

Particulary the line 502 sets mouse position to s_currWindowCtx->touchPos (which is {0,0}) every frame, when mouse is not moved. I don't understand what the intended logic behind this code was, but this is obviously wrong. I don't have any touch devices, so I can't properly test any PR, unfortunately.

Code (using imgui-sfml v3.0):

#include "imgui.h"
#include "imgui-SFML.h"
#include <SFML/Graphics.hpp>

int main()
{
	// EDIT: display child window first
    sf::RenderWindow childWindow(sf::VideoMode({640, 480}), "ImGui-SFML Child window");
    childWindow.setFramerateLimit(60);
    if (!ImGui::SFML::Init(childWindow))
        return -1;
    childWindow.setPosition({0,800});

    sf::RenderWindow window(sf::VideoMode({1280, 720}), "ImGui + SFML = <3");
    window.setFramerateLimit(60);
    if (!ImGui::SFML::Init(window))
        return -1;
    window.setPosition({0,0});

    sf::Clock deltaClock;
    while (window.isOpen())
    {
        // Main window event processing
        while (const auto event = window.pollEvent())
        {
            ImGui::SFML::ProcessEvent(window, *event);
            if (event->is<sf::Event::Closed>())
            {
                if (childWindow.isOpen())
                {
                    childWindow.close();
                }
                window.close();
                ImGui::SFML::Shutdown();
                return 0;
            }
        }

        // Child window event processing
		static sf::Color child_window_color = sf::Color::Red;
        if (childWindow.isOpen())
        {
            while (const auto event = childWindow.pollEvent())
            {
                ImGui::SFML::ProcessEvent(childWindow, *event);

				// Workaround: Deliver Event::MouseMoved to ImGui manually
				if (auto mm = event->getIf<sf::Event::MouseMoved>()) {
					const auto [x, y] = sf::Vector2f(mm->position);
					ImGui::GetIO().AddMousePosEvent(x, y);
				}

                if (event->is<sf::Event::Closed>())
                {
                    childWindow.close();
                    ImGui::SFML::Shutdown(childWindow);
                }

				if (event->is<sf::Event::MouseButtonPressed>() && !ImGui::GetIO().WantCaptureMouse)
					child_window_color.b ^= 0xFF;
            }
        }

        // Update child window
        const sf::Time dt = deltaClock.restart();
        ImGui::SFML::Update(window, dt);
        if (childWindow.isOpen())
        {
            ImGui::SFML::Update(childWindow, dt);
        }

        // Add ImGui widgets in the first window
        ImGui::SFML::SetCurrentWindow(window);
        ImGui::Begin("Hello, world!");
        ImGui::Button("Look at this pretty button");
        ImGui::End();
        ImGui::ShowDemoWindow();

        // Add ImGui widgets in the child window
        if (childWindow.isOpen())
        {
            ImGui::SFML::SetCurrentWindow(childWindow);

			// EDIT: make sure ImGui window lies at {0,0}
			ImGui::SetNextWindowPos({0,0}, ImGuiCond_Once);

            ImGui::Begin("Works in a second window!");
            ImGui::Button("Example button");
			ImGui::Text("WantCaptureMouse: %s", ImGui::GetIO().WantCaptureMouse ? "true" : "false");
            ImGui::End();
        }

        // Main window drawing
        sf::CircleShape shape(100.f);
        shape.setFillColor(sf::Color::Green);

        window.clear();
        window.draw(shape);
        ImGui::SFML::Render(window);
        window.display();

        // Child window drawing
        if (childWindow.isOpen())
        {
            sf::CircleShape shape2(50.f);
            shape2.setFillColor(child_window_color);

            childWindow.clear();
            childWindow.draw(shape2);
            ImGui::SFML::Render(childWindow);
            childWindow.display();
        }
    }
}

Demonstration:
https://github.com/user-attachments/assets/f422df29-e0da-402a-914b-c81aa5a0787d

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions