using System;
using System.Linq;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;
using FullscreenEditor.Windows;
namespace FullscreenEditor {
/// Helper for getting fullscreen rectangles.
public static class FullscreenRects {
/// Represents a callback for user defined fullscreen rect calculation.
/// The mode set in
/// A rect calculated based on custom logic.
/// Whether the rect calculated should be used or not.
public delegate bool FullscreenRectCallback(RectSourceMode mode, out Rect rect);
/// The number of monitors attached to this machine, returns -1 if the platform is not supported.
public static int ScreenCount {
get {
if (!FullscreenUtility.IsWindows)
return -1;
const int SM_CMONITORS = 80;
return User32.GetSystemMetrics(SM_CMONITORS);
}
}
/// Custom callback to allow the user to specify their own logic to how fullscreens will be arranged.
/// Check the documentation for usage examples.
public static FullscreenRectCallback CustomRectCallback { get; set; }
/// Returns a fullscreen rect
/// The mode that will be used to retrieve the rect.
/// The window that will be set fullscreen.
public static Rect GetFullscreenRect(RectSourceMode mode, ScriptableObject targetWindow = null) {
if (targetWindow != null && !targetWindow.IsOfType(typeof(EditorWindow)) && !targetWindow.IsOfType(Types.View)) {
throw new ArgumentException("Target window must be of type EditorWindow or View or null", "targetWindow");
}
if (CustomRectCallback != null) {
var rect = new Rect();
var shouldUse = CustomRectCallback(mode, out rect);
if (shouldUse)
return rect;
}
switch (mode) {
case RectSourceMode.MainDisplay:
return GetMainDisplayRect();
case RectSourceMode.WindowDisplay:
if (targetWindow == null || !FullscreenUtility.IsWindows)
return GetMainDisplayRect();
var views = new ViewPyramid(targetWindow);
var rect = views.Container.GetPropertyValue("position");
return GetDisplayBoundsAtPoint(rect.center);
case RectSourceMode.AtMousePosition:
return FullscreenUtility.IsWindows ?
GetDisplayBoundsAtPoint(FullscreenUtility.MousePosition) :
GetWorkAreaRect(true);
case RectSourceMode.Span:
return FullscreenUtility.IsWindows ?
GetVirtualScreenBounds() :
GetWorkAreaRect(true);
case RectSourceMode.Custom:
return GetCustomUserRect();
case RectSourceMode.Display1:
return GetMonitorRect(0);
case RectSourceMode.Display2:
return GetMonitorRect(1);
case RectSourceMode.Display3:
return GetMonitorRect(2);
case RectSourceMode.Display4:
return GetMonitorRect(3);
case RectSourceMode.Display5:
return GetMonitorRect(4);
case RectSourceMode.Display6:
return GetMonitorRect(5);
case RectSourceMode.Display7:
return GetMonitorRect(6);
case RectSourceMode.Display8:
return GetMonitorRect(7);
default:
Logger.Warning("Invalid fullscreen mode, please fix this by changing the placement source mode in preferences.");
return new Rect(Vector2.zero, Vector2.one * 300f);
}
}
/// Returns a rect with the dimensions of the main screen.
/// (Note that the position may not be right for multiple screen setups)
public static Rect GetMainDisplayRect() {
if (FullscreenUtility.IsWindows) {
var mainDisplay = DisplayInfo
.GetDisplays()
.FirstOrDefault(d => d.PrimaryDisplay);
if (mainDisplay != null)
return mainDisplay.UnityCorrectedArea;
Logger.Error("No main display??? This should not happen, falling back to Screen.currentResolution");
}
// Screen.currentResolution returns the resolution of the screen where
// the currently focused window is located, not the main display resolution.
// This caused the bug #53 on windows.
// The same behaviour was not tested on Linux as macOS
return new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height);
}
/// Returns the rect of a given display index.
public static Rect GetMonitorRect(int index) {
if (!FullscreenUtility.IsWindows)
return GetMainDisplayRect();
var d = DisplayInfo.GetDisplay(index);
if (d == null) {
Logger.Error("Display {0} not connected", index + 1);
return GetMainDisplayRect();
}
return d.UnityCorrectedArea;
}
/// Returns a rect defined by the user in the preferences.
public static Rect GetCustomUserRect() {
return FullscreenPreferences.CustomRect;
}
/// Returns a rect covering all the screen, except for the taskbar/dock.
/// On Windows it adds a 4px border and does not account for scaling (can cause bugs when using scales different than 100%).
/// On macOS this returns a fullscreen rect when the main window is maximized and mouseScreen is set to true.
/// Should we get the rect on the screen where the mouse pointer is?
public static Rect GetWorkAreaRect(bool mouseScreen) {
return Types.ContainerWindow.InvokeMethod("FitRectToScreen", new Rect(Vector2.zero, Vector2.one * 10000f), true, mouseScreen);
}
/// Returns a rect covering all the screen, except for the taskbar/dock.
/// On Windows it adds a 4px border and does not account for scaling (can cause bugs when using scales different than 100%).
/// On macOS this returns a fullscreen rect when the main window is maximized and mouseScreen is set to true.
/// The ContainerWindow that will be used as reference for calulating border error.
/// Should we get the rect on the screen where the mouse pointer is?
public static Rect GetWorkAreaRect(Object container, bool mouseScreen) {
return container.InvokeMethod("FitWindowRectToScreen", new Rect(Vector2.zero, Vector2.one * 10000f), true, mouseScreen);
}
/// Returns the bounds rect of the screen that contains the given point. (Windows only)
/// The point relative to
public static Rect GetDisplayBoundsAtPoint(Vector2 point) {
return InternalEditorUtility.GetBoundsOfDesktopAtPoint(point);
}
/// Full virtual screen bounds, spanning across all monitors. (Windows only)
public static Rect GetVirtualScreenBounds() {
if (!FullscreenUtility.IsWindows)
throw new NotImplementedException();
const int SM_XVIRTUALSCREEN = 76;
const int SM_YVIRTUALSCREEN = 77;
const int SM_CXVIRTUALSCREEN = 78;
const int SM_CYVIRTUALSCREEN = 79;
var x = User32.GetSystemMetrics(SM_XVIRTUALSCREEN);
var y = User32.GetSystemMetrics(SM_YVIRTUALSCREEN);
var width = User32.GetSystemMetrics(SM_CXVIRTUALSCREEN);
var height = User32.GetSystemMetrics(SM_CYVIRTUALSCREEN);
var rect = new Rect {
yMin = y,
xMin = x,
width = width,
height = height,
};
return FullscreenUtility.DpiCorrectedArea(rect);
}
}
}