#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
#if !MINIMAL
using System.Drawing;
#endif
namespace OpenTK
{
///
/// Defines a display device on the underlying system, and provides
/// methods to query and change its display parameters.
///
public class DisplayDevice
{
// TODO: Add properties that describe the 'usable' size of the Display, i.e. the maximized size without the taskbar etc.
// TODO: Does not detect changes to primary device.
#region Fields
bool primary;
Rectangle bounds;
DisplayResolution current_resolution = new DisplayResolution();
DisplayResolution original_resolution;
List available_resolutions = new List();
IList available_resolutions_readonly;
internal object Id; // A platform-specific id for this monitor
static readonly object display_lock = new object();
static DisplayDevice primary_display;
static Platform.IDisplayDeviceDriver implementation;
#endregion
#region Constructors
static DisplayDevice()
{
implementation = Platform.Factory.Default.CreateDisplayDeviceDriver();
}
internal DisplayDevice()
{
available_resolutions_readonly = available_resolutions.AsReadOnly();
}
internal DisplayDevice(DisplayResolution currentResolution, bool primary,
IEnumerable availableResolutions, Rectangle bounds,
object id)
: this()
{
// Todo: Consolidate current resolution with bounds? Can they fall out of sync right now?
this.current_resolution = currentResolution;
IsPrimary = primary;
this.available_resolutions.AddRange(availableResolutions);
#pragma warning disable 612,618
this.bounds = bounds == Rectangle.Empty ? currentResolution.Bounds : bounds;
#pragma warning restore 612,618
this.Id = id;
}
#endregion
#region --- Public Methods ---
#region public Rectangle Bounds
///
/// Gets the bounds of this instance in pixel coordinates..
///
public Rectangle Bounds
{
get { return bounds; }
internal set
{
bounds = value;
current_resolution.Height = bounds.Height;
current_resolution.Width = bounds.Width;
}
}
#endregion
#region public int Width
/// Gets a System.Int32 that contains the width of this display in pixels.
public int Width { get { return current_resolution.Width; } }
#endregion
#region public int Height
/// Gets a System.Int32 that contains the height of this display in pixels.
public int Height { get { return current_resolution.Height; } }
#endregion
#region public int BitsPerPixel
/// Gets a System.Int32 that contains number of bits per pixel of this display. Typical values include 8, 16, 24 and 32.
public int BitsPerPixel
{
get { return current_resolution.BitsPerPixel; }
internal set { current_resolution.BitsPerPixel = value; }
}
#endregion
#region public float RefreshRate
///
/// Gets a System.Single representing the vertical refresh rate of this display.
///
public float RefreshRate
{
get { return current_resolution.RefreshRate; }
internal set { current_resolution.RefreshRate = value; }
}
#endregion
#region public bool IsPrimary
/// Gets a System.Boolean that indicates whether this Display is the primary Display in systems with multiple Displays.
public bool IsPrimary
{
get { return primary; }
internal set
{
if (value && primary_display != null && primary_display != this)
primary_display.IsPrimary = false;
lock (display_lock)
{
primary = value;
if (value)
primary_display = this;
}
}
}
#endregion
#region public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate)
///
/// Selects an available resolution that matches the specified parameters.
///
/// The width of the requested resolution in pixels.
/// The height of the requested resolution in pixels.
/// The bits per pixel of the requested resolution.
/// The refresh rate of the requested resolution in hertz.
/// The requested DisplayResolution or null if the parameters cannot be met.
///
/// If a matching resolution is not found, this function will retry ignoring the specified refresh rate,
/// bits per pixel and resolution, in this order. If a matching resolution still doesn't exist, this function will
/// return the current resolution.
/// A parameter set to 0 or negative numbers will not be used in the search (e.g. if refreshRate is 0,
/// any refresh rate will be considered valid).
/// This function allocates memory.
///
public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate)
{
DisplayResolution resolution = FindResolution(width, height, bitsPerPixel, refreshRate);
if (resolution == null)
resolution = FindResolution(width, height, bitsPerPixel, 0);
if (resolution == null)
resolution = FindResolution(width, height, 0, 0);
if (resolution == null)
return current_resolution;
return resolution;
}
#endregion
#region public IList AvailableResolutions
///
/// Gets the list of objects available on this device.
///
public IList AvailableResolutions
{
get { return available_resolutions_readonly; }
internal set
{
available_resolutions = (List)value;
available_resolutions_readonly = available_resolutions.AsReadOnly();
}
}
#endregion
#region public void ChangeResolution(DisplayResolution resolution)
/// Changes the resolution of the DisplayDevice.
/// The resolution to set.
/// Thrown if the requested resolution could not be set.
/// If the specified resolution is null, this function will restore the original DisplayResolution.
public void ChangeResolution(DisplayResolution resolution)
{
if (resolution == null)
this.RestoreResolution();
if (resolution == current_resolution)
return;
//effect.FadeOut();
if (implementation.TryChangeResolution(this, resolution))
{
if (original_resolution == null)
original_resolution = current_resolution;
current_resolution = resolution;
}
else throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to change resolution to {1}.",
this, resolution));
//effect.FadeIn();
}
#endregion
#region public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate)
/// Changes the resolution of the DisplayDevice.
/// The new width of the DisplayDevice.
/// The new height of the DisplayDevice.
/// The new bits per pixel of the DisplayDevice.
/// The new refresh rate of the DisplayDevice.
/// Thrown if the requested resolution could not be set.
public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate)
{
this.ChangeResolution(this.SelectResolution(width, height, bitsPerPixel, refreshRate));
}
#endregion
#region public void RestoreResolution()
/// Restores the original resolution of the DisplayDevice.
/// Thrown if the original resolution could not be restored.
public void RestoreResolution()
{
if (original_resolution != null)
{
//effect.FadeOut();
if (implementation.TryRestoreResolution(this))
{
current_resolution = original_resolution;
original_resolution = null;
}
else throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to restore resolution.", this));
//effect.FadeIn();
}
}
#endregion
#region public static IList AvailableDisplays
///
/// Gets the list of available objects.
/// This function allocates memory.
///
[Obsolete("Use GetDisplay(DisplayIndex) instead.")]
public static IList AvailableDisplays
{
get
{
List displays = new List();
for (int i = 0; i < 6; i++)
{
DisplayDevice dev = GetDisplay(DisplayIndex.First + i);
if (dev != null)
displays.Add(dev);
}
return displays.AsReadOnly();
}
}
#endregion
#region public static DisplayDevice Default
/// Gets the default (primary) display of this system.
public static DisplayDevice Default
{
get { return implementation.GetDisplay(DisplayIndex.Primary); }
}
#endregion
#region GetDisplay
///
/// Gets the for the specified .
///
/// The that defines the desired display.
/// A or null, if no device corresponds to the specified index.
public static DisplayDevice GetDisplay(DisplayIndex index)
{
return implementation.GetDisplay(index);
}
#endregion
#endregion
#region --- Internal Methods ---
#region internal DisplayResolution OriginalResolution
///
/// Gets the original resolution of this instance.
///
internal DisplayResolution OriginalResolution
{
get { return original_resolution; }
set { original_resolution = value; }
}
#endregion
#region FromPoint
internal static DisplayDevice FromPoint(int x, int y)
{
for (DisplayIndex i = DisplayIndex.First; i < DisplayIndex.Sixth; i++)
{
DisplayDevice display = DisplayDevice.GetDisplay(i);
if (display != null)
{
if (display.Bounds.Contains(x, y))
{
return display;
}
}
}
return null;
}
#endregion
#endregion
#region --- Private Methods ---
#region DisplayResolution FindResolution(int width, int height, int bitsPerPixel, float refreshRate)
DisplayResolution FindResolution(int width, int height, int bitsPerPixel, float refreshRate)
{
return available_resolutions.Find(delegate(DisplayResolution test)
{
return
((width > 0 && width == test.Width) || width == 0) &&
((height > 0 && height == test.Height) || height == 0) &&
((bitsPerPixel > 0 && bitsPerPixel == test.BitsPerPixel) || bitsPerPixel == 0) &&
((refreshRate > 0 && System.Math.Abs(refreshRate - test.RefreshRate) < 1.0) || refreshRate == 0);
});
}
#endregion
#endregion
#region --- Overrides ---
#region public override string ToString()
///
/// Returns a System.String representing this DisplayDevice.
///
/// A System.String representing this DisplayDevice.
public override string ToString()
{
return String.Format("{0}: {1} ({2} modes available)", IsPrimary ? "Primary" : "Secondary",
Bounds.ToString(), available_resolutions.Count);
}
#endregion
#region public override bool Equals(object obj)
///// Determines whether the specified DisplayDevices are equal.
///// The System.Object to check against.
///// True if the System.Object is an equal DisplayDevice; false otherwise.
//public override bool Equals(object obj)
//{
// if (obj is DisplayDevice)
// {
// DisplayDevice dev = (DisplayDevice)obj;
// return
// IsPrimary == dev.IsPrimary &&
// current_resolution == dev.current_resolution &&
// available_resolutions.Count == dev.available_resolutions.Count;
// }
// return false;
//}
#endregion
#region public override int GetHashCode()
///// Returns a unique hash representing this DisplayDevice.
///// A System.Int32 that may serve as a hash code for this DisplayDevice.
////public override int GetHashCode()
//{
// return current_resolution.GetHashCode() ^ IsPrimary.GetHashCode() ^ available_resolutions.Count;
//}
#endregion
#endregion
}
#region --- FadeEffect ---
#if false
class FadeEffect : IDisposable
{
List