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

Games receive joypad input even if the game window is not focused #16832

Open
BeayemX opened this issue Feb 19, 2018 · 30 comments · May be fixed by #82965
Open

Games receive joypad input even if the game window is not focused #16832

BeayemX opened this issue Feb 19, 2018 · 30 comments · May be fixed by #82965

Comments

@BeayemX
Copy link
Contributor

BeayemX commented Feb 19, 2018

Godot version:

3925e6a

OS/device including version:

Tested on Linux Mint 18.3 sylvia

Issue description:

When running multiple Godot games all games will receive the joypad input. It does not matter if the games are started from the editor or if they are run from the commandline.

Steps to reproduce:

  1. Run two godot games at the same time and use a joypad.
  2. See that both games will process the joypad input regardless of the window focus
@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

This is not a bug. If this was not intended... well... this bug turns into feature. What is the problem to allow user to play with joypad if focus was lost?. If you want not let user to play when focus was lost, maybe you should pause the game on focus lost.

Playing Ori and the blind forest... on focus lost: Pause.
Playing Shadows of war... on focus lost: pause, but if you enter in settings and see control type, if you lost focus with keyboard, game pauses, but if you touch the gamepad, game icon changes, so the game, in pause, is registering gamepad input.

So this is a standard behavior i think.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

Playing Hyper Light Drifter: On focus lost you can play the game. I´m playing now, and writing text... I open godot project, press play and both, my demo and hyper light drifter uses the joypad. This is expected behavior please.

The stanley parable: if you lost focus on windowed you can change options with gamepad.

@BeayemX
Copy link
Contributor Author

BeayemX commented Feb 19, 2018

The problem I had was when testing network functionality of my game (locally) and both the server and client were reacting to the joypad input.

I am not quite convinced that this isn't a bug. Because I think it is strange that the game reacts to joypad input but not to keyboard input when not focused.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

I put some examples of that. All this games on focus lost don´t react to keyboard but react to gamepad.

@Ranoller
Copy link
Contributor

Why do you not filter joypad input on server?

@BeayemX
Copy link
Contributor Author

BeayemX commented Feb 19, 2018

I could do that but the same thing applies when testing with multiple local clients. I could ignore input when not focused, but as I stated I think this is not the desired behavior.

I opened this issue because it was mentioned in #15199 by @akien-mga

The fact that multiple instances of a game all receive joypad events regardless of the focus would likely be worth keeping track of in a new issue (if not done already).

If this really is intended behavior this issue can be closed.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

I don´t know if is intended, but for me is dessired because is the normal behavior of PC games. Some games pauses in focus lost, others allows you to play with gamepad input. See this, i open stanley parable and don´t starve:
gamepadfocuslost
Same controler in menu...
A workaround for your problem can be an option in settings to only allow one window to handle input in preview... but in release i think that this can be a mistake.

@vnen
Copy link
Member

vnen commented Feb 19, 2018

I don't think this has any "intention", it's all based on the underlying OS API. Usually the OS only send key and mouse events to the focused window (or to window directly under the cursor, for mouse wheel events). But gamepad events are usually sent to all windows that are listening to it, regardless of focus.

I don't know if we want to override the system behavior. But maybe there could be an easy way for the game dev to decide whether the input should be stopped or not when the window is out of focus.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

There are some constants defined in MainLoop called:

NOTIFICATION_WM_MOUSE_ENTER = 2

NOTIFICATION_WM_MOUSE_EXIT = 3

NOTIFICATION_WM_FOCUS_IN = 4

NOTIFICATION_WM_FOCUS_OUT = 5

But there in no notify() method in this class to use that, and i can´t find any documented method that allow to do that... so maybe is needed and easy way to notify focus_lost / focus_gain or something like this...

But for the problem of @BeayemX there is a bool method in Scenetree: Scenetree.is_network_server() that returns true if the scenetree is in server mode, so maybe can incorporate that to _input(event) to filter all the inputs if this is true (Not tested, only an idea)

@BeayemX
Copy link
Contributor Author

BeayemX commented Feb 19, 2018

The function you are looking for is this

'''
func _notification(what):
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
get_tree().quit()

'''

@Ranoller
Copy link
Contributor

And works!. So with a little tutorial in docs handle focus in window is easy...

@vnen
Copy link
Member

vnen commented Feb 19, 2018

You can use notifications to check the focus change, that is not much the problem. The thing is that if you want to disable input, there's no way to do it globally, so you'd have to add a lot of ifs in every place you are using input.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 19, 2018

I see... i don´t think in that because i handle all input in unique global script, but is true that if using _input(event) in a lot of scripts this can be cumbersome.

@Ranoller
Copy link
Contributor

Ranoller commented Feb 20, 2018

If you do a singleton with:

var Unfocused = false

func _notification(what):
    if what == MainLoop.NOTIFICATION_WM_FOCUS_OUT: 
        Unfocused = true
    elif what == MainLoop.NOTIFICATION_WM_FOCUS_IN: 
        Unfocused = false

func _input(event):
if Unfocused: get_tree().set_input_as_handled()

It can handle all input in focus lost?... Other idea (But i agree that this should be more intuitive/friendly to do)

Edit2: Works well, but only with _input(event). It stop propagation to all scripts, but if you use Input in _process or _fixed/physics_process that solution doesn´t work.

@Zylann
Copy link
Contributor

Zylann commented Feb 20, 2018

It's a common issue that usually happens with game vs GUI in games. When you poll input using "direct global" functions like Input.get_axis, you explicitely bypass any focus barrier (contrary to event based approach) so it's expected. Solution is indeed either use event approach, or use ifs to filter.

@KoBeWi
Copy link
Member

KoBeWi commented Jun 13, 2020

I don't think this has any "intention", it's all based on the underlying OS API. Usually the OS only send key and mouse events to the focused window (or to window directly under the cursor, for mouse wheel events). But gamepad events are usually sent to all windows that are listening to it, regardless of focus.

Worth to mention that this is optional. Unfocused/minimized windows can get keyboard input too if they want so (I don't know the exact details, but that's e.g. how keyloggers work :P). So it would make sense if the unfocused window receiving gamepad was optional too, even if it has to be filtered by the engine.

Still valid in 58034f3 btw.

@brianwinterpixel
Copy link
Contributor

This should absolutely be a project setting that can be toggled.

In games that have interactions with real consequences such as making purchases in-game, modifying settings, or joining online matches, handling joypad inputs while the game is running in the background out-of-sight can cause real consequences for players and developers.

Requiring developers to implement their own system for blocking joypad input while the window is out of focus is error prone and hacky.

@Calinou Calinou added this to the 4.0 milestone Jan 10, 2022
@mischiefaaron
Copy link

This should absolutely be a project setting that can be toggled.

In games that have interactions with real consequences such as making purchases in-game, modifying settings, or joining online matches, handling joypad inputs while the game is running in the background out-of-sight can cause real consequences for players and developers.

Requiring developers to implement their own system for blocking joypad input while the window is out of focus is error prone and hacky.

Having an option is definitely the ideal even just for me alone. I have gamepad visualizer application I'd like it to work out of focus and my games which I'd like to stop taking gamepad input when work out of focus.

@atngames
Copy link
Contributor

I support the "project setting" idea !
I try to develop a game launcher and definitely need to tackle this problem.

@Calinou
Copy link
Member

Calinou commented Jul 20, 2022

I started working on adding a setting to adjust this behavior: https://github.com/Calinou/godot/tree/input-joypad-ignore-when-unfocused

This also involves readding an equivalent to OS.is_window_focused() in 4.0, which was removed as part of the DisplayServer refactoring.

@czlowiekimadlo
Copy link

Any news on this one? Today I noticed, that on Steam Deck, when you open the system menu over the game, it still captures all the input underneath while you try to navigate it, making it a real problem on this platform.

@YuriSizov YuriSizov modified the milestones: 4.0, 4.x Feb 24, 2023
@Calinou
Copy link
Member

Calinou commented May 8, 2023

Note that a script-based workaround is now documented in Controllers, gamepads and joysticks. This change was done by godotengine/godot-docs#7292 and godotengine/godot-docs#7313.

A PR to implement this toggle as a built-in project setting is still welcome (for both 4.x and 3.x), but I don't have time to work on it currently.

Any news on this one? Today I noticed, that on Steam Deck, when you open the system menu over the game, it still captures all the input underneath while you try to navigate it, making it a real problem on this platform.

Don't a lot of non-Godot games run into this issue too? This sounds like something Valve should resolve on their end.

@joemicmc
Copy link

joemicmc commented May 9, 2023

Note that a script-based workaround is now documented in Controllers, gamepads and joysticks. This change was done by godotengine/godot-docs#7292 and godotengine/godot-docs#7313.

@Calinou was that just a change to the documentation? The notifications listed in the documentation don't seem to be available in 4.0.2-stable.

Edit: Ah. I wasn't extending a Node, but a RefCounted so had to access constant via Node.NOTIFICATION...

@Calinou

This comment was marked as outdated.

@joemicmc
Copy link

joemicmc commented May 9, 2023

Ah interesting, this page says every Object implements _notification() https://docs.godotengine.org/en/stable/tutorials/best_practices/godot_notifications.html

@Calinou
Copy link
Member

Calinou commented May 9, 2023

Ah interesting, this page says every Object implements _notification() docs.godotengine.org/en/stable/tutorials/best_practices/godot_notifications.html

Nevermind, I read the editor help tree wrong. Every Object indeed calls _notification().

@joemicmc
Copy link

joemicmc commented May 9, 2023

One thing I've picked up on with the script-based workaround is that you'll get problems with the built-in UI actions (e.g. ui_left, ui_right etc.). I've added my own UI actions (so they are only processed when the window is focused) and then fire the built-in action using documentation at https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html#actions:

var ev = InputEventAction.new()
# Set as ui_down, pressed.
ev.action = "ui_down"
ev.pressed = true
# Feedback.
Input.parse_input_event(ev)

@ssokolow
Copy link

ssokolow commented Sep 29, 2023

Can we also get something in the docs to encourage that the choice be exposed to the user and providing some example code for how to manipulate the setting programmatically?

Being able to use a gamepad to control an unfocused game is such a desired behaviour for me that, if a game pauses on loss of focus and it can't be disabled, I'll force the issue by removing the game's ability detect loss of focus by either running it in Wine in Virtual Desktop mode or running it on my dedicated Win7 gaming machine and then using either my KVM switch and an extra Linux-only mouse or the monitor's internal input selector to merge that into my three-monitor spread as if it were fullscreened on my Linux machine's centre monitor.

@Chtau Chtau linked a pull request Oct 7, 2023 that will close this issue
@Gatada
Copy link
Contributor

Gatada commented Oct 26, 2023

Currently I can enable "No Focus" in advanced Project Settings, so the running game does not steal focus away from the editor—allowing me to playtest with the controller while modifying the script in the editor.

This is a very welcome productivity boost for me.

I would hate if any solution to this "bug" breaks this workflow.

@Calinou
Copy link
Member

Calinou commented Oct 26, 2023

I would hate if any solution to this "bug" breaks this workflow.

We don't intend to disable unfocused gamepad events by default – the current behavior will remain the default. This behavior is desired for things like Nucleus Coop after all 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

Successfully merging a pull request may close this issue.