I’m doing an Editor extension and I want to update an application wide state once the Editor has gained focus. For example once the user Alt+Tabs into another window and then returns back to the Editor.
UnityEditorInternal.InternalEditorUtility.isApplicationActive
will return true, if the Editor window is focused in any way. Was pretty hard to find, because it’s not documented, but InternalEditorUtility
is a gem, there is much to discover.
The solutions proposed in other answers (@Nikolay-Lezhnev & @llMarty) already work correctly, but let me suggest an alternative method.
Using reflection, we can access the exact same event that Unity uses internally.
public static Action<bool> UnityEditorFocusChanged
{
get
{
var fieldInfo = typeof(EditorApplication).GetField("focusChanged",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
return (Action<bool>)fieldInfo.GetValue(null);
}
set
{
var fieldInfo = typeof(EditorApplication).GetField("focusChanged",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
fieldInfo.SetValue(null, value);
}
}
You can then register to the event like you would with any delegate:
UnityEditorFocusChanged += OnEditorFocusChanged;
And the signature for your callbacks must be as follows:
private static void OnEditorFocusChanged(bool hasFocus)
{
if (hasFocus)
{
EditorWindow.focusedWindow?.ShowNotification(new GUIContent("Welcome back! ^_^"));
}
}
You can also add this script to Assets/Editor:
using System;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class EditorWindowFocusUtility
{
public static event Action<bool> OnUnityEditorFocus = (focus) => { };
private static bool _appFocused;
static EditorWindowFocusUtility()
{
EditorApplication.update += Update;
}
private static void Update()
{
if (!_appFocused && UnityEditorInternal.InternalEditorUtility.isApplicationActive)
{
_appFocused = UnityEditorInternal.InternalEditorUtility.isApplicationActive;
OnUnityEditorFocus(true);
Debug.Log("On focus window!");
}
else if (_appFocused && !UnityEditorInternal.InternalEditorUtility.isApplicationActive)
{
_appFocused = UnityEditorInternal.InternalEditorUtility.isApplicationActive;
OnUnityEditorFocus(false);
Debug.Log("On lost focus");
}
}
}
and you can subscribe in any place on event:
EditorWindowFocusUtility.OnUnityEditorFocus += (focus) => {/*do something*/}
I Found a cheaty way. Apparently the EditorWindow
has a private property called hasFocus
. I just use reflection to access it. This will give delegate:
Delegate.CreateDelegate(typeof(Func<EditorWindow,bool>),typeof(EditorWindow).GetProperty("hasFocus", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true));
I’m curious about this too
Here is what I use:
public static bool IsUnityEditorFocused() {
return EditorWindow.mouseOverWindow != null;
}
Final solution: a regular script (non-Editor) with this code:
–
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
#endif
using UnityEngine;
public static class ApplicationUtility
{
// A generic "is focused" method that also returns true when the Unity application window
// is active, regardless the specific editor window that is focused.
public static bool IsActivated()
{
#if UNITY_EDITOR
return InternalEditorUtility.isApplicationActive;
#else
return Application.isFocused;
#endif
}
}
–
Then you may detect whether the application is focused by calling ApplicationUtility.IsActivated()
from anywhere, and would work regardless being a built application or being run within the Editor.
Declaration :
public void Focus();
Description :
Moves keyboard focus to another EditorWindow.
The Focus public method controls which window is active for use of the keyboard. In the examples below the active EditorWindow keyboard is changed to a different EditorWindow
InternalEditorUtility.isApplicationActive
will return true, if the Editor window is focused in any way. Was pretty hard to find, because it’s not documented, but InternalEditorUtility
is a gem, there is much to discover.