@@ -22,107 +22,120 @@ internal enum FocusFlags : ushort
2222 /// <summary>
2323 /// In editor this means the GameView has focus. In a built player this means the player has focus.
2424 /// </summary>
25- ApplicationFocus = ( 1 << 0 )
25+ ApplicationFocus = ( 1 << 0 ) ,
2626 } ;
2727
2828 internal partial class InputManager
2929 {
3030 internal void OnFocusChanged ( bool focus )
3131 {
32+ // We set this to temporarily override applicationHasFocus before processing the focus change
33+ // as defaultUpdateType is influenced by it. Before returning from this method, clear the
34+ // bool to stop overriding to indicate this manager has finished processing the focus change.
35+ m_IsHandlingFocusChange = true ;
36+ m_ApplicationHadFocus = ! focus ;
37+
3238#if UNITY_EDITOR
33- SyncAllDevicesWhenEditorIsActivated ( ) ;
39+ var shouldClearCurrentUpdateInFinally = false ;
40+ #endif
3441
35- if ( ! m_Runtime . isInPlayMode )
42+ try
3643 {
37- focusState = focus ? FocusFlags . ApplicationFocus : FocusFlags . None ;
38- return ;
39- }
44+ #if UNITY_EDITOR
45+ SyncAllDevicesWhenEditorIsActivated ( ) ;
46+
47+ if ( ! m_Runtime . isInPlayMode )
48+ return ;
4049
41- var gameViewFocus = m_Settings . editorInputBehaviorInPlayMode ;
50+ var gameViewFocus = m_Settings . editorInputBehaviorInPlayMode ;
4251#endif
4352
44- var runInBackground =
53+ var runInBackground =
4554#if UNITY_EDITOR
46- // In the editor, the player loop will always be run even if the Game View does not have focus. This
47- // amounts to runInBackground being always true in the editor, regardless of what the setting in
48- // the Player Settings window is.
49- //
50- // If, however, "Game View Focus" is set to "Exactly As In Player", we force code here down the same
51- // path as in the player.
52- gameViewFocus != InputSettings . EditorInputBehaviorInPlayMode . AllDeviceInputAlwaysGoesToGameView || m_Runtime . runInBackground ;
55+ // In the editor, the player loop will always be run even if the Game View does not have focus. This
56+ // amounts to runInBackground being always true in the editor, regardless of what the setting in
57+ // the Player Settings window is.
58+ //
59+ // If, however, "Game View Focus" is set to "Exactly As In Player", we force code here down the same
60+ // path as in the player.
61+ gameViewFocus != InputSettings . EditorInputBehaviorInPlayMode . AllDeviceInputAlwaysGoesToGameView || m_Runtime . runInBackground ;
5362#else
54- m_Runtime . runInBackground ;
63+ m_Runtime . runInBackground ;
5564#endif
5665
57- var backgroundBehavior = m_Settings . backgroundBehavior ;
58- if ( backgroundBehavior == InputSettings . BackgroundBehavior . IgnoreFocus && runInBackground )
59- {
60- // If runInBackground is true, no device changes should happen, even when focus is gained. So early out.
61- // If runInBackground is false, we still want to sync devices when focus is gained. So we need to continue further.
62- focusState = focus ? FocusFlags . ApplicationFocus : FocusFlags . None ;
63- return ;
64- }
66+ if ( m_Settings . backgroundBehavior == InputSettings . BackgroundBehavior . IgnoreFocus && runInBackground )
67+ {
68+ // If runInBackground is true, no device changes should happen, even when focus is gained. So early out.
69+ // If runInBackground is false, we still want to sync devices when focus is gained. So we need to continue further.
70+ return ;
71+ }
6572
6673#if UNITY_EDITOR
67- // Set the current update type while we process the focus changes to make sure we
68- // feed into the right buffer. No need to do this in the player as it doesn't have
69- // the editor/player confusion.
70- m_CurrentUpdate = m_UpdateMask . GetUpdateTypeForPlayer ( ) ;
74+ // Set the current update type while we process the focus changes to make sure we
75+ // feed into the right buffer. No need to do this in the player as it doesn't have
76+ // the editor/player confusion.
77+ m_CurrentUpdate = m_UpdateMask . GetUpdateTypeForPlayer ( ) ;
78+ shouldClearCurrentUpdateInFinally = true ;
7179#endif
7280
73- if ( ! focus )
74- {
75- // We only react to loss of focus when we will keep running in the background. If not,
76- // we'll do nothing and just wait for focus to come back (where we then try to sync all devices).
77- if ( runInBackground )
81+ if ( ! focus )
7882 {
79- for ( var i = 0 ; i < m_DevicesCount ; ++ i )
83+ // We only react to loss of focus when we will keep running in the background. If not,
84+ // we'll do nothing and just wait for focus to come back (where we then try to sync all devices).
85+ if ( runInBackground )
8086 {
81- // Determine whether to run this device in the background.
82- var device = m_Devices [ i ] ;
83- if ( ! device . enabled || ShouldRunDeviceInBackground ( device ) )
84- continue ;
87+ for ( var i = 0 ; i < m_DevicesCount ; ++ i )
88+ {
89+ // Determine whether to run this device in the background.
90+ var device = m_Devices [ i ] ;
91+ if ( ! device . enabled || ShouldRunDeviceInBackground ( device ) )
92+ continue ;
8593
86- // Disable the device. This will also soft-reset it.
87- EnableOrDisableDevice ( device , false , DeviceDisableScope . TemporaryWhilePlayerIsInBackground ) ;
94+ // Disable the device. This will also soft-reset it.
95+ EnableOrDisableDevice ( device , false , DeviceDisableScope . TemporaryWhilePlayerIsInBackground ) ;
8896
89- // In case we invoked a callback that messed with our device array, adjust our index.
90- var index = m_Devices . IndexOfReference ( device , m_DevicesCount ) ;
91- if ( index == - 1 )
92- -- i ;
93- else
94- i = index ;
97+ // In case we invoked a callback that messed with our device array, adjust our index.
98+ var index = m_Devices . IndexOfReference ( device , m_DevicesCount ) ;
99+ if ( index == - 1 )
100+ -- i ;
101+ else
102+ i = index ;
103+ }
95104 }
96105 }
97- }
98- else
99- {
100- m_DiscardOutOfFocusEvents = true ;
101- m_FocusRegainedTime = m_Runtime . currentTime ;
102- // On focus gain, reenable and sync devices.
103- for ( var i = 0 ; i < m_DevicesCount ; ++ i )
106+ else
104107 {
105- var device = m_Devices [ i ] ;
108+ m_DiscardOutOfFocusEvents = true ;
109+ m_FocusRegainedTime = m_Runtime . currentTime ;
110+
111+ // On focus gain, reenable and sync devices.
112+ for ( var i = 0 ; i < m_DevicesCount ; ++ i )
113+ {
114+ var device = m_Devices [ i ] ;
106115
107- // Re-enable the device if we disabled it on focus loss. This will also issue a sync.
108- if ( device . disabledWhileInBackground )
109- EnableOrDisableDevice ( device , true , DeviceDisableScope . TemporaryWhilePlayerIsInBackground ) ;
110- // Try to sync. If it fails and we didn't run in the background, perform
111- // a reset instead. This is to cope with backends that are unable to sync but
112- // may still retain state which now may be outdated because the input device may
113- // have changed state while we weren't running. So at least make the backend flush
114- // its state (if any).
115- else if ( device . enabled && ! runInBackground && ! device . RequestSync ( ) && m_Settings . backgroundBehavior != InputSettings . BackgroundBehavior . IgnoreFocus )
116- ResetDevice ( device ) ;
116+ // Re-enable the device if we disabled it on focus loss. This will also issue a sync.
117+ if ( device . disabledWhileInBackground )
118+ EnableOrDisableDevice ( device , true , DeviceDisableScope . TemporaryWhilePlayerIsInBackground ) ;
119+
120+ // Try to sync. If it fails and we didn't run in the background, perform
121+ // a reset instead. This is to cope with backends that are unable to sync but
122+ // may still retain state which now may be outdated because the input device may
123+ // have changed state while we weren't running. So at least make the backend flush
124+ // its state (if any).
125+ else if ( device . enabled && ! runInBackground && ! device . RequestSync ( ) && m_Settings . backgroundBehavior != InputSettings . BackgroundBehavior . IgnoreFocus )
126+ ResetDevice ( device ) ;
127+ }
117128 }
118129 }
119-
130+ finally
131+ {
120132#if UNITY_EDITOR
121- m_CurrentUpdate = InputUpdateType . None ;
133+ if ( shouldClearCurrentUpdateInFinally )
134+ m_CurrentUpdate = InputUpdateType . None ;
122135#endif
123136
124- // We set this *after* the block above as defaultUpdateType is influenced by the setting.
125- focusState = focus ? FocusFlags . ApplicationFocus : FocusFlags . None ;
137+ m_IsHandlingFocusChange = false ;
138+ }
126139 }
127140
128141 /// <summary>
@@ -150,8 +163,6 @@ private bool ShouldFlushEventBuffer()
150163 /// <summary>
151164 /// Determines if we should exit early from event processing without handling events.
152165 /// </summary>
153- /// <param name="eventBuffer">The current event buffer</param>
154- /// <param name="canFlushBuffer">Whether the buffer can be flushed</param>
155166 /// <param name="updateType">The current update type</param>
156167 /// <returns>True if we should exit early, false otherwise.</returns>
157168 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
0 commit comments