- Home /
Editor Window - How to center a window.
Like the title said, how does one center a popup window for a instance in the Editor?
Using Screen.Width does not work, unless the window is in full screen, and in the primary monitor.
Answer by Bunny83 · May 05, 2015 at 05:31 PM
So i guess your actual question is how you can find out the position and size of Unity's main window? Here you go:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
public static class Extensions
{
public static System.Type[] GetAllDerivedTypes(this System.AppDomain aAppDomain, System.Type aType)
{
var result = new List<System.Type>();
var assemblies = aAppDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes();
foreach (var type in types)
{
if (type.IsSubclassOf(aType))
result.Add(type);
}
}
return result.ToArray();
}
public static Rect GetEditorMainWindowPos()
{
var containerWinType = System.AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ScriptableObject)).Where(t => t.Name == "ContainerWindow").FirstOrDefault();
if (containerWinType == null)
throw new System.MissingMemberException("Can't find internal type ContainerWindow. Maybe something has changed inside Unity");
var showModeField = containerWinType.GetField("m_ShowMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var positionProperty = containerWinType.GetProperty("position", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (showModeField == null || positionProperty == null)
throw new System.MissingFieldException("Can't find internal fields 'm_ShowMode' or 'position'. Maybe something has changed inside Unity");
var windows = Resources.FindObjectsOfTypeAll(containerWinType);
foreach (var win in windows)
{
var showmode = (int)showModeField.GetValue(win);
if (showmode == 4) // main window
{
var pos = (Rect)positionProperty.GetValue(win, null);
return pos;
}
}
throw new System.NotSupportedException("Can't find internal main window. Maybe something has changed inside Unity");
}
public static void CenterOnMainWin(this UnityEditor.EditorWindow aWin)
{
var main = GetEditorMainWindowPos();
var pos = aWin.position;
float w = (main.width - pos.width)*0.5f;
float h = (main.height - pos.height)*0.5f;
pos.x = main.x + w;
pos.y = main.y + h;
aWin.position = pos;
}
}
Just use Extensions.GetEditorMainWindowPos() to get back the rect of the main window in screen coordinates.
I've also written a simple extension method for the EditorWindow class called "CenterOnMainWin". So inside yout editor window you can simply call CenterOnMainWin() and the window should positioning itself in the center of the main window.
Of course, as you can see on the safety checks, it's possible that this method breaks in the future since we access internal classes / variables via reflection. It's very unlikely that those things will be changed but i just want to say that it's possible.
On the other hand Unity also changed the official API and deprecates things from now and then. So you never have a guarantee that anything will still work in a few years.
edit
Also note that when calling Extensions.GetEditor$$anonymous$$ainWindowPos() or CenterOn$$anonymous$$ainWin() it searches through all class types that exists within Unity and your current project. Then it also uses Resources.FindObjectsOfTypeAll which searches through all objects within Unity. So it's not recommended to call this method on a regular basis (update delegate or OnGUI).
It could be optimised by caching the PropertyInfo value and the mainWindow container window value in a static variable.
Exactly what I needed, and now I feel dumb for not thinking in Reflecting to get the window position.!!
Edit : Quick Question though, how did you find name ContainerWindow? Or how did you know that it was the correct one?
@morphex: Well, i studied Unity's GUI system way back and i know most of the internal structures ^^ (at least on the managed side).
An EditorWindow is actually just a ScriptableObject. That instance is wrapped in a HostView (which is responsible for the "tabs" at the top). The HostView might be embedded in a SplitView (if there are multiple EditorWindows attached next to each other". Finally at the top of the chain you will find the ContainerWindow (also a ScriptableObject) which represents an actual window (in the sense of OS GUI).
There's a special View called $$anonymous$$ainWindow which is the actual View that represents the main window. When the ContainerWindow for the $$anonymous$$ainWindow view is created / shown it uses "Show$$anonymous$$ode.$$anonymous$$ainWindow" (which is an enum and has the value "4"). The showmode is stored inside the ContainerWindow in the internal variable "m_Show$$anonymous$$ode". So you just have to find a ContainerWindow with that showmode and you know it's the main window ^^
This answer was powered by:
http://ilspy.net/
Thanks for the code. Pretty much to do to just get the correct center of the screen. This solution was the only one working for me. So I've used this code to create a 200x200 sized window in the screen center:
popup window = ScriptableObject.CreateInstance();
window.position = new Rect(0, 0, 200, 200);
Extensions.CenterOn$$anonymous$$ainWin(window);
Note that CenterOn$$anonymous$$ainWin is an extension method. So you can simply do
window.CenterOn$$anonymous$$ainWin();
Also note that this code does not center the window on the screen or desktop but just relative to the Unity main window. Since many people nowadays have a multi-monitor setups and an extended desktop, centering on the desktop wouldn't make much sense.
Be aware that a new method was added to Unity 2020: EditorGUIUtility.Get$$anonymous$$ainWindowPosition(). It acts the same way as GetEditor$$anonymous$$ainWindowPos() and is obviously faster, so you should use only the CenterOn$$anonymous$$ainWin method with the following modification:
public static void CenterOn$$anonymous$$ainWin(this UnityEditor.EditorWindow aWin)
{
var main = EditorGUIUtility.Get$$anonymous$$ainWindowPosition();
var pos = aWin.position;
float w = (main.width - pos.width)*0.5f;
float h = (main.height - pos.height)*0.5f;
pos.x = main.x + w;
pos.y = main.y + h;
aWin.position = pos;
}
Answer by ThomLaurent · May 31, 2017 at 11:51 AM
Actually the correct answer would rather be:
var window = GetWindow<MyWindow>("Centered Window");
var position = window.position;
position.center = new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center;
window.position = position;
window.Show();
using Screen.currentResolution.width
and Screen.currentResolution.height
.
I would be careful with absolute terms like "correct". The question wasn't about centering the window in the main-screen but centered inside the Unity$$anonymous$$ain window. For example if you have Unity on your second monitor your code would still open the window centered on the main monitor.
EditorWindows are sub-windows of the Unity editor and logically belong to Unity itself and do not act like seperate programs. Your code works for centering an editor window on the main monitor but that's not necessarily what you want.
Answer by SolidAlloy · Oct 14, 2020 at 01:00 PM
There is a new method added to Unity 2020: EditorGUIUtility.GetMainWindowPosition().
It acts the same way as GetEditorMainWindowPos() but it's obviously faster, so you should use only the CenterOnMainWin method from the Bunny83's answer with the following modification:
public static void CenterOnMainWin(this EditorWindow window)
{
Rect main = EditorGUIUtility.GetMainWindowPosition();
Rect pos = window.position;
float centerWidth = (main.width - pos.width) * 0.5f;
float centerHeight = (main.height - pos.height) * 0.5f;
pos.x = main.x + centerWidth;
pos.y = main.y + centerHeight;
window.position = pos;
}
Answer by Darcy_zh · Nov 30, 2021 at 07:48 AM
If without 2020, doing this will be much faster
private static Type GetType (this AppDomain aAppDomain, Type aType, string name)
{
var assemblies = aAppDomain.GetAssemblies ();
return assemblies.SelectMany (assembly => assembly.GetTypes ()).FirstOrDefault (type => type.IsSubclassOf (aType) && type.Name == name);
}
var containerWinType =
AppDomain.CurrentDomain.GetType (typeof (ScriptableObject), "ContainerWindow");
Answer by diogosnows · Mar 23 at 01:45 PM
I was having a similar issue and to get Unity's window center I'm now using:
var windowCenter = EditorGUIUtility.GetMainWindowPosition().center;
I haven't tested this across multiple setups, but is also working on a recent MacBook which was an issue before.
Your answer
![](https://koobas.hobune.stream/wayback/20220613194812im_/https://answers.unity.com/themes/thub/images/avi.jpg)