Godot: Games receive joypad input even if the game window is not focused

Created on 19 Feb 2018  路  16Comments  路  Source: godotengine/godot

Godot version:

3925e6a5431424f422273f3522016a9d6a51a876

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
bug confirmed core

Most helpful comment

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.

All 16 comments

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.

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.

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.

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

Why do you not filter joypad input on server?

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.

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.

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.

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)

The function you are looking for is this

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

'''

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

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.

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.

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.

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.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gonzo191 picture gonzo191  路  3Comments

nunodonato picture nunodonato  路  3Comments

SleepProgger picture SleepProgger  路  3Comments

Zylann picture Zylann  路  3Comments

testman42 picture testman42  路  3Comments