Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't care about focus when processing events / updating #227

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 86 additions & 105 deletions imgui-SFML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ struct WindowContext {
sf::Texture fontTexture; // internal font atlas which is used if user doesn't set a custom
// sf::Texture.

bool windowHasFocus;
bool mouseMoved;
bool mousePressed[3];
ImGuiMouseCursor lastCursor;
Expand Down Expand Up @@ -214,7 +213,6 @@ struct WindowContext {
window = w;
imContext = ImGui::CreateContext();

windowHasFocus = window->hasFocus();
mouseMoved = false;
for (int i = 0; i < 3; ++i) {
mousePressed[i] = false;
Expand Down Expand Up @@ -553,95 +551,83 @@ void ProcessEvent(const sf::Event& event) {
assert(s_currWindowCtx && "No current window is set - forgot to call ImGui::SFML::Init?");
ImGuiIO& io = ImGui::GetIO();

if (s_currWindowCtx->windowHasFocus) {
switch (event.type) {
case sf::Event::Resized:
io.DisplaySize = ImVec2(event.size.width, event.size.height);
break;
case sf::Event::MouseMoved:
io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y);
s_currWindowCtx->mouseMoved = true;
break;
case sf::Event::MouseButtonPressed: // fall-through
case sf::Event::MouseButtonReleased: {
int button = event.mouseButton.button;
if (button >= 0 && button < 3) {
if (event.type == sf::Event::MouseButtonPressed) {
s_currWindowCtx->mousePressed[event.mouseButton.button] = true;
io.AddMouseButtonEvent(button, true);
} else {
io.AddMouseButtonEvent(button, false);
}
}
} break;
case sf::Event::TouchBegan: // fall-through
case sf::Event::TouchEnded: {
s_currWindowCtx->mouseMoved = false;
int button = event.touch.finger;
if (event.type == sf::Event::TouchBegan && button >= 0 && button < 3) {
s_currWindowCtx->touchDown[event.touch.finger] = true;
}
} break;
case sf::Event::MouseWheelScrolled:
if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel ||
(event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel && io.KeyShift)) {
io.AddMouseWheelEvent(0, event.mouseWheelScroll.delta);
} else if (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel) {
io.AddMouseWheelEvent(event.mouseWheelScroll.delta, 0);
}
break;
case sf::Event::KeyPressed: // fall-through
case sf::Event::KeyReleased: {
bool down = (event.type == sf::Event::KeyPressed);

ImGuiKey mod = keycodeToImGuiMod(event.key.code);
// The modifier booleans are not reliable when it's the modifier
// itself that's being pressed. Detect these presses directly.
if (mod != ImGuiKey_None) {
io.AddKeyEvent(mod, down);
switch (event.type) {
case sf::Event::Resized:
io.DisplaySize = ImVec2(event.size.width, event.size.height);
break;
case sf::Event::MouseMoved:
io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y);
s_currWindowCtx->mouseMoved = true;
break;
case sf::Event::MouseButtonPressed: // fall-through
case sf::Event::MouseButtonReleased: {
int button = event.mouseButton.button;
if (button >= 0 && button < 3) {
if (event.type == sf::Event::MouseButtonPressed) {
s_currWindowCtx->mousePressed[event.mouseButton.button] = true;
io.AddMouseButtonEvent(button, true);
} else {
io.AddKeyEvent(ImGuiKey_ModCtrl, event.key.control);
io.AddKeyEvent(ImGuiKey_ModShift, event.key.shift);
io.AddKeyEvent(ImGuiKey_ModAlt, event.key.alt);
io.AddKeyEvent(ImGuiKey_ModSuper, event.key.system);
io.AddMouseButtonEvent(button, false);
}

ImGuiKey key = keycodeToImGuiKey(event.key.code);
io.AddKeyEvent(key, down);
io.SetKeyEventNativeData(key, event.key.code, -1);
} break;
case sf::Event::TextEntered:
// Don't handle the event for unprintable characters
if (event.text.unicode < ' ' || event.text.unicode == 127) {
break;
}
io.AddInputCharacter(event.text.unicode);
break;
case sf::Event::JoystickConnected:
if (s_currWindowCtx->joystickId == NULL_JOYSTICK_ID) {
s_currWindowCtx->joystickId = event.joystickConnect.joystickId;
}
break;
case sf::Event::JoystickDisconnected:
if (s_currWindowCtx->joystickId == event.joystickConnect.joystickId) { // used gamepad
// was
// disconnected
s_currWindowCtx->joystickId = getConnectedJoystickId();
}
break;
default:
break;
}
break;
}
case sf::Event::TouchBegan: // fall-through
case sf::Event::TouchEnded: {
s_currWindowCtx->mouseMoved = false;
int button = event.touch.finger;
if (event.type == sf::Event::TouchBegan && button >= 0 && button < 3) {
s_currWindowCtx->touchDown[event.touch.finger] = true;
}
break;
}
case sf::Event::MouseWheelScrolled:
if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel ||
(event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel && io.KeyShift)) {
io.AddMouseWheelEvent(0, event.mouseWheelScroll.delta);
} else if (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel) {
io.AddMouseWheelEvent(event.mouseWheelScroll.delta, 0);
}
break;
case sf::Event::KeyPressed: // fall-through
case sf::Event::KeyReleased: {
bool down = (event.type == sf::Event::KeyPressed);

ImGuiKey mod = keycodeToImGuiMod(event.key.code);
// The modifier booleans are not reliable when it's the modifier
// itself that's being pressed. Detect these presses directly.
if (mod != ImGuiKey_None) {
io.AddKeyEvent(mod, down);
} else {
io.AddKeyEvent(ImGuiKey_ModCtrl, event.key.control);
io.AddKeyEvent(ImGuiKey_ModShift, event.key.shift);
io.AddKeyEvent(ImGuiKey_ModAlt, event.key.alt);
io.AddKeyEvent(ImGuiKey_ModSuper, event.key.system);
}

switch (event.type) {
case sf::Event::LostFocus: {
io.AddFocusEvent(false);
s_currWindowCtx->windowHasFocus = false;
} break;
case sf::Event::GainedFocus:
io.AddFocusEvent(true);
s_currWindowCtx->windowHasFocus = true;
ImGuiKey key = keycodeToImGuiKey(event.key.code);
io.AddKeyEvent(key, down);
io.SetKeyEventNativeData(key, event.key.code, -1);
break;
}
case sf::Event::TextEntered:
// Don't handle the event for unprintable characters
if (event.text.unicode < ' ' || event.text.unicode == 127) {
break;
}
io.AddInputCharacter(event.text.unicode);
break;
case sf::Event::JoystickConnected:
if (s_currWindowCtx->joystickId == NULL_JOYSTICK_ID) {
s_currWindowCtx->joystickId = event.joystickConnect.joystickId;
}
break;
case sf::Event::JoystickDisconnected:
if (s_currWindowCtx->joystickId == event.joystickConnect.joystickId) { // used gamepad
// was
// disconnected
s_currWindowCtx->joystickId = getConnectedJoystickId();
}
break;
default:
break;
Expand Down Expand Up @@ -680,21 +666,18 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T
io.DisplaySize = ImVec2(displaySize.x, displaySize.y);
io.DeltaTime = dt.asSeconds();

if (s_currWindowCtx->windowHasFocus) {
if (io.WantSetMousePos) {
sf::Vector2i newMousePos(static_cast<int>(io.MousePos.x),
static_cast<int>(io.MousePos.y));
sf::Mouse::setPosition(newMousePos);
} else {
io.MousePos = ImVec2(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
}
for (unsigned int i = 0; i < 3; i++) {
io.MouseDown[i] = s_currWindowCtx->touchDown[i] || sf::Touch::isDown(i) ||
s_currWindowCtx->mousePressed[i] ||
sf::Mouse::isButtonPressed((sf::Mouse::Button)i);
s_currWindowCtx->mousePressed[i] = false;
s_currWindowCtx->touchDown[i] = false;
}
if (io.WantSetMousePos) {
sf::Vector2i newMousePos(static_cast<int>(io.MousePos.x), static_cast<int>(io.MousePos.y));
sf::Mouse::setPosition(newMousePos);
} else {
io.MousePos = ImVec2(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
}
for (unsigned int i = 0; i < 3; i++) {
io.MouseDown[i] = s_currWindowCtx->touchDown[i] || sf::Touch::isDown(i) ||
s_currWindowCtx->mousePressed[i] ||
sf::Mouse::isButtonPressed((sf::Mouse::Button)i);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oprypin I see what you're saying now - it's because this directly queries the mouse state here which bypasses the event queue.

Ideally think this should use events instead?

Copy link
Contributor Author

@eliasdaler eliasdaler Feb 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it looks like this is what causes problems, thanks.
I guess I should really rework how ProcessEvent/Update/Render etc. work and not use any direct queries since they don't respect window focus.

Of course, maybe if I check s_currWindowCtx.window->hasFocus(), it might solve the problem, but it feels somewhat hacky.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, this doesn't solve the problem for hover events... Sad.

s_currWindowCtx->mousePressed[i] = false;
s_currWindowCtx->touchDown[i] = false;
}

#ifdef ANDROID
Expand Down Expand Up @@ -1317,9 +1300,7 @@ void updateJoystickButtonState(ImGuiIO& io) {
ImGuiKey key = s_currWindowCtx->joystickMapping[i];
if (key != ImGuiKey_None) {
bool isPressed = sf::Joystick::isButtonPressed(s_currWindowCtx->joystickId, i);
if (s_currWindowCtx->windowHasFocus || !isPressed) {
io.AddKeyEvent(key, isPressed);
}
io.AddKeyEvent(key, isPressed);
}
}
}
Expand All @@ -1331,7 +1312,7 @@ void updateJoystickAxis(ImGuiIO& io, ImGuiKey key, sf::Joystick::Axis axis, floa
pos = -pos;
}
bool passedThreshold = (pos > threshold) == (maxThreshold > threshold);
if (passedThreshold && s_currWindowCtx->windowHasFocus) {
if (passedThreshold) {
io.AddKeyAnalogEvent(key, true, std::abs(pos / 100.f));
} else {
io.AddKeyAnalogEvent(key, false, 0);
Expand Down