Synced gl4 branch with trunk.

This commit is contained in:
the_fiddler 2010-12-04 19:02:50 +00:00
commit ddb0f67048
109 changed files with 8105 additions and 3092 deletions

20
QuickStart.sln Normal file
View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickStart", "Source\QuickStart\QuickStart.csproj", "{90762BBE-CB23-42FF-9D3E-486D2F6CA485}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AnyCPU = Debug|AnyCPU
Release|AnyCPU = Release|AnyCPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{90762BBE-CB23-42FF-9D3E-486D2F6CA485}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{90762BBE-CB23-42FF-9D3E-486D2F6CA485}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{90762BBE-CB23-42FF-9D3E-486D2F6CA485}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{90762BBE-CB23-42FF-9D3E-486D2F6CA485}.Release|AnyCPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Source\QuickStart\QuickStart.csproj
EndGlobalSection
EndGlobal

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -7,8 +7,6 @@
<ProjectGuid>{31D19132-0000-0000-0000-000000000000}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>Bind</AssemblyName>
@ -21,8 +19,6 @@
<AppDesignerFolder>
</AppDesignerFolder>
<RootNamespace>Bind</RootNamespace>
<StartupObject>
</StartupObject>
<StartArguments>
</StartArguments>
<FileUpgradeFlags>
@ -47,73 +43,60 @@
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>True</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>False</Optimize>
<Optimize>false</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Debug\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>False</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>True</Optimize>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>False</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>True</Optimize>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
@ -1055,6 +1038,7 @@
</None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)' == 'Documentation'">
<OutputPath>..\..\Binaries\OpenTK\Release</OutputPath>
@ -26,17 +26,45 @@
<RootNamespace>Build.UpdateVersion</RootNamespace>
<OutputType>Exe</OutputType>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Documentation|AnyCPU' ">
<DebugType>none</DebugType>
<DefineConstants>TRACE;</DefineConstants>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<DefineConstants>TRACE;</DefineConstants>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Nsis|AnyCPU' ">
<DebugType>none</DebugType>
<DefineConstants>TRACE;</DefineConstants>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Target Name="BeforeBuild">
<Delete Files="..\..\Version.txt" />
</Target>

View file

@ -26,20 +26,38 @@
#endregion
using System;
using System.Diagnostics;
using System.IO;
namespace Build.UpdateVersion
{
class Program
{
class Program
{
const string Major = "1";
const string Minor = "1";
static string RootDirectory;
static string SourceDirectory;
public static void Main()
{
string wdir = Environment.CurrentDirectory;
if (Directory.GetParent(wdir).Name == "Source")
{
// Running through msbuild inside Source/Build.UpdateVersion/
RootDirectory = "../..";
SourceDirectory = "..";
}
else
{
// Running manually inside Binaries/OpenTK/[Debug|Release]/
RootDirectory = "../../..";
SourceDirectory = "../../../Source";
}
DateTime now = DateTime.UtcNow;
GenerateVersionInfo(now, "../../Version.txt");
GenerateAssemblyInfo(now, "../GlobalAssemblyInfo.cs");
GenerateVersionInfo(now, Path.Combine(RootDirectory, "Version.txt"));
GenerateAssemblyInfo(now, Path.Combine(SourceDirectory, "GlobalAssemblyInfo.cs"));
}
static void GenerateVersionInfo(DateTime now, string file)
@ -54,7 +72,7 @@ namespace Build.UpdateVersion
version = lines[0];
}
}
// If the file does not exist, create it.
if (version == null)
{
@ -69,7 +87,9 @@ namespace Build.UpdateVersion
// Revision number is defined as the fraction of the current day, expressed in seconds.
double timespan = now.Subtract(new DateTime(2010, 1, 1)).TotalDays;
string build = ((int)timespan).ToString();
string revision = ((int)((timespan - (int)timespan) * UInt16.MaxValue)).ToString();
string revision = RetrieveSvnRevision() ?? RetrieveBzrRevision() ?? RetrieveSeconds(timespan);
revision = revision.Trim();
File.WriteAllLines(file, new string[]
{
@ -90,5 +110,59 @@ namespace Build.UpdateVersion
String.Format("[assembly: AssemblyFileVersion(\"{0}.{1}.{2}.{3}\")]", Major, Minor, build, revision),
});
}
}
}
static string RetrieveSeconds(double timespan)
{
string revision = ((int)((timespan - (int)timespan) * UInt16.MaxValue)).ToString();
return revision;
}
static string RetrieveSvnRevision()
{
try
{
string output = RunProcess("svn", "info", RootDirectory);
const string RevisionText = "Revision: ";
int index = output.IndexOf(RevisionText);
if (index > -1)
return output.Substring(index + RevisionText.Length, 5)
.Replace('\r', ' ').Replace('\n', ' ').Trim();
}
catch (Exception e)
{
Debug.Print("Failed to retrieve svn revision. Error: {0}", e);
}
return null;
}
static string RetrieveBzrRevision()
{
try
{
string output = RunProcess("bzr", "revno", RootDirectory);
return output != null && !output.StartsWith("bzr") ? output : null;
}
catch (Exception e)
{
Debug.Print("Failed to retrieve svn revision. Error: {0}", e);
}
return null;
}
static string RunProcess(string cmd, string args, string wdir)
{
ProcessStartInfo info = new ProcessStartInfo(cmd, args);
info.WorkingDirectory = wdir;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
Process p = new Process();
p.StartInfo = info;
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
return output;
}
}
}

View file

@ -363,7 +363,5 @@ namespace OpenTK.Audio
public static EaxReverb Chapel = new EaxReverb(26, 19.6f, 0.840f, -1000, -500, 0, 4.62f, 0.64f, 1.23f, -700, 0.032f, 0f, 0f, 0f, -200, 0.049f, 0f, 0f, 0f, 0.250f, 0f, 0.250f, 0.110f, -5f, 5000f, 250f, 0f, 0x3f);
public static EaxReverb Smallwaterroom = new EaxReverb(26, 36.2f, 0.700f, -1000, -698, 0, 1.51f, 1.25f, 1.14f, -100, 0.020f, 0f, 0f, 0f, 300, 0.030f, 0f, 0f, 0f, 0.179f, 0.150f, 0.895f, 0.190f, -7f, 5000f, 250f, 0f, 0x0);
}
#pragma warning restore 1591
}
}

View file

@ -1312,11 +1312,6 @@ namespace OpenTK.Graphics
#endregion
#pragma warning restore 3019
#pragma warning restore 1591
#pragma warning restore 1572
#pragma warning restore 1573
#endregion
}
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -47,7 +47,8 @@
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE;</DefineConstants>
<DocumentationFile>OpenTK.Compatibility.xml</DocumentationFile>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>false</Optimize>
@ -55,7 +56,7 @@
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<WarningLevel>4</WarningLevel>
<NoWarn>1591</NoWarn>
<NoWarn>0219, 0414, 0612, 0618, 1591, 3005, 3006</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>full</DebugType>
</PropertyGroup>
@ -65,19 +66,25 @@
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>OpenTK.Compatibility.xml</DocumentationFile>
<DocumentationFile>
</DocumentationFile>
<FileAlignment>4096</FileAlignment>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<WarningLevel>4</WarningLevel>
<NoWarn>1591</NoWarn>
<NoWarn>0219, 0414, 0612, 0618, 1591, 3005, 3006</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<NoWarn>0219, 0414, 0612, 0618, 1591, 3005, 3006</NoWarn>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -85,14 +92,15 @@
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>OpenTK.Compatibility.xml</DocumentationFile>
<DocumentationFile>
</DocumentationFile>
<FileAlignment>4096</FileAlignment>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<WarningLevel>4</WarningLevel>
<NoWarn>1591</NoWarn>
<NoWarn>0219, 0414, 0612, 0618, 1591, 3005, 3006</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
@ -475,6 +483,11 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="OpenTK.Compatibility.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -7,8 +7,6 @@
<ProjectGuid>{5FDFF4B6-0000-0000-0000-000000000000}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>Convert</AssemblyName>
@ -21,8 +19,6 @@
<AppDesignerFolder>
</AppDesignerFolder>
<RootNamespace>Convert</RootNamespace>
<StartupObject>
</StartupObject>
<StartArguments>
</StartArguments>
<FileUpgradeFlags>
@ -45,73 +41,60 @@
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>True</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>False</Optimize>
<Optimize>false</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Debug\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>False</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>True</Optimize>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>False</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>True</Optimize>
<Optimize>true</Optimize>
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>
</NoWarn>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
@ -184,6 +167,7 @@
</None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>

View file

@ -42,10 +42,8 @@ namespace Examples
#region Fields
//PrivateFontCollection font_collection = new PrivateFontCollection();
bool show_warning = true;
static readonly string SourcePath = FindSourcePath();
readonly string SourcePath;
#endregion
@ -53,6 +51,10 @@ namespace Examples
public ExampleBrowser()
{
SourcePath =
FindSourcePath(Directory.GetCurrentDirectory()) ??
FindSourcePath(Assembly.GetExecutingAssembly().Location);
Font = SystemFonts.DialogFont;
InitializeComponent();
@ -121,7 +123,8 @@ namespace Examples
const string no_docs = "Documentation has not been entered.";
const string no_source = "Source code has not been entered.";
if (e.Node.Tag != null && !String.IsNullOrEmpty(((ExampleInfo)e.Node.Tag).Attribute.Documentation))
if (SourcePath != null && e.Node.Tag != null &&
!String.IsNullOrEmpty(((ExampleInfo)e.Node.Tag).Attribute.Documentation))
{
string docs = null;
string source = null;
@ -358,7 +361,10 @@ namespace Examples
MethodInfo main =
e.Example.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ??
e.Example.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(object), typeof(object) }, null);
e.Example.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] {
typeof(object),
typeof(object)
}, null);
if (main != null)
{
try
@ -371,31 +377,13 @@ namespace Examples
Trace.WriteLine(String.Format("Launching sample: \"{0}\"", e.Attribute.Title));
Trace.WriteLine(String.Empty);
Thread thread = new Thread((ThreadStart)delegate
{
try
{
main.Invoke(null, null);
}
catch (TargetInvocationException expt)
{
string ex_info;
if (expt.InnerException != null)
ex_info = expt.InnerException.ToString();
else
ex_info = expt.ToString();
MessageBox.Show(ex_info, "An OpenTK example encountered an error.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
AppDomain sandbox = AppDomain.CreateDomain("Sandbox");
sandbox.DomainUnload += HandleSandboxDomainUnload;
Debug.Print(expt.ToString());
}
catch (NullReferenceException expt)
{
MessageBox.Show(expt.ToString(), "The Example launcher failed to load the example.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
});
thread.IsBackground = true;
thread.Start();
thread.Join();
SampleRunner runner = new SampleRunner(main);
CrossAppDomainDelegate cross = new CrossAppDomainDelegate(runner.Invoke);
sandbox.DoCallBack(cross);
AppDomain.Unload(sandbox);
}
finally
{
@ -412,31 +400,68 @@ namespace Examples
}
}
// Tries to detect the path that contains the source for the examples.
static string FindSourcePath()
static void HandleSandboxDomainUnload(object sender, EventArgs e)
{
string current_dir = Directory.GetCurrentDirectory();
AppDomain sandbox = (AppDomain)sender;
sandbox.DomainUnload -= HandleSandboxDomainUnload;
}
[Serializable]
class SampleRunner
{
MethodInfo _main;
public SampleRunner(MethodInfo main)
{
_main = main;
}
public void Invoke()
{
try
{
_main.Invoke(null, null);
}
catch (TargetInvocationException expt)
{
string ex_info;
if (expt.InnerException != null)
ex_info = expt.InnerException.ToString();
else
ex_info = expt.ToString();
//MessageBox.Show(ex_info, "An OpenTK example encountered an error.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Trace.WriteLine(ex_info.ToString());
}
catch (Exception expt)
{
Trace.WriteLine(expt.ToString());
}
}
}
// Tries to detect the path that contains the source for the examples.
static string FindSourcePath(string guess)
{
guess = Path.GetDirectoryName(guess);
// Typically, our working directory is either "[opentk]/Binaries/OpenTK/[config]" or "[opentk]".
// The desired source path is "[opentk]/Source/Examples/[ExampleCategory]"
string guess = current_dir;
if (CheckPath(ref guess))
return guess; // We were in [opentk] after all
guess = current_dir;
for (int i = 0; i < 3; i++)
{
DirectoryInfo dir = Directory.GetParent(guess);
if (!dir.Exists)
if (dir == null || !dir.Exists)
break;
guess = dir.FullName;
}
if (CheckPath(ref guess))
return guess; // We were in [opentk]/Binaries/OpenTK/[config] after all
throw new DirectoryNotFoundException();
return null;
}
static bool CheckPath(ref string path)

View file

@ -0,0 +1,204 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
namespace Examples.Tutorial
{
[Example( "Anaglyph Stereo", ExampleCategory.OpenGL, "1.x", Documentation = "Anaglyph" )]
class Anaglyph : GameWindow
{
Examples.Shapes.DrawableShape Object;
/// <summary>Creates a 800x600 window with the specified title.</summary>
public Anaglyph()
: base(800, 600, GraphicsMode.Default, "OpenTK Quick Start Sample", GameWindowFlags.Default, DisplayDevice.Default, 3, 1, GraphicsContextFlags.Default)
{
VSync = VSyncMode.On;
}
/// <summary>Load resources here.</summary>
/// <param name="e">Not used.</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.ClearColor(System.Drawing.Color.Black);
GL.Enable(EnableCap.DepthTest);
GL.Enable( EnableCap.Lighting );
GL.Enable( EnableCap.Light0 );
Object = new Examples.Shapes.MengerSponge(1.0, Shapes.MengerSponge.eSubdivisions.Two, true );
// Object = new Examples.Shapes.TorusKnot( 256, 32, 0.1, 3, 4, 1, true );
}
protected override void OnUnload( EventArgs e )
{
base.OnUnload( e );
Object.Dispose();
}
/// <summary>
/// Called when your window is resized. Set your viewport here. It is also
/// a good place to set up your projection matrix (which probably changes
/// along when the aspect ratio of your window).
/// </summary>
/// <param name="e">Not used.</param>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GL.Viewport(ClientRectangle);
}
/// <summary>
/// Called when it is time to setup the next frame. Add you game logic here.
/// </summary>
/// <param name="e">Contains timing information for framerate independent logic.</param>
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (Keyboard[Key.Escape])
Exit();
}
struct Camera
{
public Vector3 Position, Direction, Up;
public double NearPlane, FarPlane;
public double EyeSeparation;
public double Aperture; // FOV in degrees
public double FocalLength;
}
enum Eye
{
left,
right,
}
void SetupCamera( Eye eye )
{
Camera camera;
camera.Position = Vector3.UnitZ;
camera.Up = Vector3.UnitY;
camera.Direction = -Vector3.UnitZ;
camera.NearPlane = 1.0;
camera.FarPlane = 5.0;
camera.FocalLength = 2.0;
camera.EyeSeparation = camera.FocalLength / 30.0;
camera.Aperture = 75.0;
double left, right,
bottom, top;
double widthdiv2 = camera.NearPlane * Math.Tan( MathHelper.DegreesToRadians( (float)( camera.Aperture / 2.0 ) ) ); // aperture in radians
double precalc1 = ClientRectangle.Width / (double)ClientRectangle.Height * widthdiv2;
double precalc2 = 0.5 * camera.EyeSeparation * camera.NearPlane / camera.FocalLength;
Vector3 Right = Vector3.Cross( camera.Direction, camera.Up ); // Each unit vectors
Right.Normalize();
Right.X *= (float)( camera.EyeSeparation / 2.0 );
Right.Y *= (float)( camera.EyeSeparation / 2.0 );
Right.Z *= (float)( camera.EyeSeparation / 2.0 );
// Projection Matrix
top = widthdiv2;
bottom = -widthdiv2;
if ( eye == Eye.right )
{
left = -precalc1 - precalc2;
right = precalc1 - precalc2;
}
else
{
left = -precalc1 + precalc2;
right = precalc1 + precalc2;
}
GL.MatrixMode( MatrixMode.Projection );
GL.LoadIdentity();
GL.Frustum( left, right, bottom, top, camera.NearPlane, camera.FarPlane );
// Modelview Matrix
Matrix4 modelview;
if ( eye == Eye.right )
{
modelview = Matrix4.LookAt(
new Vector3( camera.Position.X + Right.X, camera.Position.Y + Right.Y, camera.Position.Z + Right.Z ),
new Vector3( camera.Position.X + Right.X + camera.Direction.X, camera.Position.Y + Right.Y + camera.Direction.Y, camera.Position.Z + Right.Z + camera.Direction.Z ),
camera.Up );
}
else
{
modelview = Matrix4.LookAt(
new Vector3( camera.Position.X - Right.X, camera.Position.Y - Right.Y, camera.Position.Z - Right.Z ),
new Vector3( camera.Position.X - Right.X + camera.Direction.X, camera.Position.Y - Right.Y + camera.Direction.Y, camera.Position.Z - Right.Z + camera.Direction.Z ),
camera.Up );
}
GL.MatrixMode( MatrixMode.Modelview );
GL.LoadIdentity();
GL.MultMatrix( ref modelview );
}
float Angle;
void Draw()
{
GL.Translate( 0f, 0f, -2f );
GL.Rotate( Angle, Vector3.UnitY );
Object.Draw();
}
/// <summary>
/// Called when it is time to render the next frame. Add your rendering code here.
/// </summary>
/// <param name="e">Contains timing information.</param>
protected override void OnRenderFrame( FrameEventArgs e )
{
Angle += (float)(e.Time *20.0);
GL.Clear( ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit );
SetupCamera( Eye.right );
GL.ColorMask( true, false, false, true );
Draw();
GL.Clear( ClearBufferMask.DepthBufferBit ); //
SetupCamera( Eye.left );
GL.ColorMask( false, true, true, true );
Draw();
GL.ColorMask( true, true, true, true );
SwapBuffers();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// The 'using' idiom guarantees proper resource cleanup.
// We request 30 UpdateFrame events per second, and unlimited
// RenderFrame events (as fast as the computer can handle).
using (Anaglyph game = new Anaglyph())
{
game.Run(10.0);
}
}
}
}

Binary file not shown.

View file

@ -21,7 +21,7 @@ namespace Examples.Tutorial
public class SimpleFBO : GameWindow
{
public SimpleFBO()
: base(800, 600)
: base(800, 400)
{
}
@ -33,24 +33,7 @@ namespace Examples.Tutorial
const int TextureSize = 512;
#region Randoms
Random rnd = new Random();
public const float scale = 3f;
/// <summary>Returns a random Float in the range [-0.5*scale..+0.5*scale]</summary>
public float GetRandom()
{
return (float)(rnd.NextDouble() - 0.5) * scale;
}
/// <summary>Returns a random Float in the range [0..1]</summary>
public float GetRandom0to1()
{
return (float)rnd.NextDouble();
}
#endregion Randoms
Examples.Shapes.DrawableShape Object;
protected override void OnLoad(EventArgs e)
{
@ -63,13 +46,14 @@ namespace Examples.Tutorial
Exit();
}
Object = new Shapes.TorusKnot(256, 16, 0.2, 7,8, 1, true);
GL.Enable(EnableCap.DepthTest);
GL.ClearDepth(1.0f);
GL.DepthFunc(DepthFunction.Lequal);
GL.Disable(EnableCap.CullFace);
GL.PolygonMode(MaterialFace.Back, PolygonMode.Line);
GL.Enable(EnableCap.CullFace);
// Create Color Tex
GL.GenTextures(1, out ColorTexture);
GL.BindTexture(TextureTarget.Texture2D, ColorTexture);
@ -176,20 +160,24 @@ namespace Examples.Tutorial
GL.ClearColor(1f, 0f, 0f, 0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// smack 50 random triangles into the FBO's textures
GL.Begin(BeginMode.Triangles);
{
for (int i = 0; i < 50; i++)
{
GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
}
}
GL.End();
OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView( MathHelper.PiOver4, TextureSize / (float)TextureSize, 2.5f, 6f );
GL.MatrixMode( MatrixMode.Projection );
GL.LoadMatrix( ref perspective );
Matrix4 lookat = Matrix4.LookAt( 0f, 0f, 4.5f, 0f, 0f, 0f, 0f, 1f, 0f );
GL.MatrixMode( MatrixMode.Modelview );
GL.LoadMatrix( ref lookat );
// draw some complex object into the FBO's textures
GL.Enable( EnableCap.Lighting );
GL.Enable( EnableCap.Light0 );
GL.Enable( EnableCap.ColorMaterial );
GL.Color3( 0f, 1f, 0f );
Object.Draw();
GL.Disable( EnableCap.ColorMaterial );
GL.Disable( EnableCap.Light0 );
GL.Disable( EnableCap.Lighting );
}
GL.PopAttrib();
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // disable rendering into the FBO
@ -203,6 +191,8 @@ namespace Examples.Tutorial
protected override void OnUnload(EventArgs e)
{
Object.Dispose();
// Clean up what we allocated before exiting
if (ColorTexture != 0)
GL.DeleteTextures(1, ref ColorTexture);

View file

@ -0,0 +1,438 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
namespace Examples.Tutorial
{
[Example( "OpenGL Diagnostics", ExampleCategory.OpenGL, "1.x", Documentation = "OpenGLDiagnostics" )]
class GLDiagnostics : GameWindow
{
/// <summary>Creates a 800x600 window with the specified title.</summary>
public GLDiagnostics()
: base(80, 60, GraphicsMode.Default, "OpenTK Quick Start Sample", GameWindowFlags.Default, DisplayDevice.Default, 3, 1, GraphicsContextFlags.Default)
{
VSync = VSyncMode.On;
this.Context.ErrorChecking = false;
}
struct TexFormat
{
public PixelInternalFormat pif;
public PixelFormat pf;
public PixelType pt;
public TexFormat(PixelInternalFormat _pif, PixelFormat _pf, PixelType _pt)
{
pif = _pif;
pf = _pf;
pt = _pt;
}
}
TexFormat[] TextureFormats = new TexFormat[]
{
new TexFormat( PixelInternalFormat.Alpha, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Alpha4, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Alpha8, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Alpha12, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Alpha16, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.Alpha16fArb, PixelFormat.Alpha, PixelType.HalfFloat),
new TexFormat( (PixelInternalFormat)All.Alpha32fArb, PixelFormat.Alpha, PixelType.Float),
new TexFormat( PixelInternalFormat.DepthComponent, PixelFormat.DepthComponent, PixelType.Int),
new TexFormat( PixelInternalFormat.DepthComponent16, PixelFormat.DepthComponent, PixelType.Float),
new TexFormat( PixelInternalFormat.DepthComponent24, PixelFormat.DepthComponent, PixelType.Float),
new TexFormat( PixelInternalFormat.DepthComponent32, PixelFormat.DepthComponent, PixelType.Float),
new TexFormat( PixelInternalFormat.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float),
new TexFormat( PixelInternalFormat.DepthStencil, PixelFormat.DepthStencil, PixelType.UnsignedInt248),
new TexFormat( PixelInternalFormat.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248),
new TexFormat( PixelInternalFormat.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev),
new TexFormat( PixelInternalFormat.One, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Two, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgba, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Srgb, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.SrgbAlpha, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Srgb8, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.R16f, PixelFormat.Red, PixelType.HalfFloat),
new TexFormat( PixelInternalFormat.Rg16f, PixelFormat.Rg, PixelType.HalfFloat),
new TexFormat( PixelInternalFormat.Rgb16f, PixelFormat.Rgb, PixelType.HalfFloat),
new TexFormat( PixelInternalFormat.Rgba16f, PixelFormat.Rgba, PixelType.HalfFloat),
new TexFormat( PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float),
new TexFormat( PixelInternalFormat.Rg32f, PixelFormat.Rg, PixelType.Float),
new TexFormat( PixelInternalFormat.Rgb32f, PixelFormat.Rgb, PixelType.Float),
new TexFormat( PixelInternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float),
new TexFormat( PixelInternalFormat.R8, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rg8, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb8, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.R8ui, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rg8ui, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb8ui, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgba8ui, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.R16ui, PixelFormat.Red, PixelType.UnsignedShort),
new TexFormat( PixelInternalFormat.Rg16ui, PixelFormat.Rg, PixelType.UnsignedShort),
new TexFormat( PixelInternalFormat.Rgb16ui, PixelFormat.Rgb, PixelType.UnsignedShort),
new TexFormat( PixelInternalFormat.Rgba16ui, PixelFormat.Rgba, PixelType.UnsignedShort),
new TexFormat( PixelInternalFormat.R32ui, PixelFormat.Red, PixelType.UnsignedInt),
new TexFormat( PixelInternalFormat.Rg32ui, PixelFormat.Rg, PixelType.UnsignedInt),
new TexFormat( PixelInternalFormat.Rgb32ui, PixelFormat.Rgb, PixelType.UnsignedInt),
new TexFormat( PixelInternalFormat.Rgba32ui, PixelFormat.Rgba, PixelType.UnsignedInt),
new TexFormat( PixelInternalFormat.R8i, PixelFormat.Red, PixelType.Byte),
new TexFormat( PixelInternalFormat.Rg8i, PixelFormat.Rg, PixelType.Byte),
new TexFormat( PixelInternalFormat.Rgb8i, PixelFormat.Rgb, PixelType.Byte),
new TexFormat( PixelInternalFormat.Rgba8i, PixelFormat.Rgba, PixelType.Byte),
new TexFormat( PixelInternalFormat.R16i, PixelFormat.Red, PixelType.Short),
new TexFormat( PixelInternalFormat.Rg16i, PixelFormat.Rg, PixelType.Short),
new TexFormat( PixelInternalFormat.Rgb16i, PixelFormat.Rgb, PixelType.Short),
new TexFormat( PixelInternalFormat.Rgba16i, PixelFormat.Rgba, PixelType.Short),
new TexFormat( PixelInternalFormat.R32i, PixelFormat.Red, PixelType.Int),
new TexFormat( PixelInternalFormat.Rg32i, PixelFormat.Rg, PixelType.Int),
new TexFormat( PixelInternalFormat.Rgb32i, PixelFormat.Rgb, PixelType.Int),
new TexFormat( PixelInternalFormat.Rgba32i, PixelFormat.Rgba, PixelType.Int),
new TexFormat( PixelInternalFormat.R3G3B2, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb5A1, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.Rgb9E5, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.R11fG11fB10f, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedAlpha, PixelFormat.Alpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedIntensity, PixelFormat.Luminance, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedLuminance, PixelFormat.Luminance, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedLuminanceAlpha, PixelFormat.LuminanceAlpha, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedLuminanceLatc1Ext, PixelFormat.Luminance, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedLuminanceAlphaLatc2Ext, PixelFormat.LuminanceAlpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRed, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRedRgtc1, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRedGreenRgtc2Ext, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRg, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRgRgtc2, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRgb, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbFxt13Dfx, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedRgba, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbaFxt13Dfx, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedSignedLuminanceAlphaLatc2Ext, PixelFormat.LuminanceAlpha, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedSignedLuminanceLatc1Ext, PixelFormat.Luminance, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSignedRedRgtc1, PixelFormat.Red, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSignedRgRgtc2, PixelFormat.Rg, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSluminance, PixelFormat.Luminance, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSluminanceAlpha, PixelFormat.LuminanceAlpha, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgb, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgbAlpha, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgbS3tcDxt1Ext, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgbAlphaS3tcDxt1Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbS3tcDxt1Ext, PixelFormat.Rgb, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbaS3tcDxt1Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbaS3tcDxt3Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
new TexFormat( (PixelInternalFormat)All.CompressedRgbaS3tcDxt5Ext, PixelFormat.Rgba, PixelType.UnsignedByte),
};
#region GL.Get* Helper
public enum eType
{
Boolean,
Int,
IntEnum,
IntArray2,
IntArray4,
Float,
FloatArray2,
FloatArray4,
}
public void Analyze(GetPName pname, eType type)
{
bool result1b;
int result1i;
int[] result2i = new int[2];
int[] result4i = new int[4];
float result1f;
Vector2 result2f;
Vector4 result4f;
string output;
switch (type)
{
case eType.Boolean:
GL.GetBoolean(pname, out result1b);
output = pname + ": " + result1b;
break;
case eType.Int:
GL.GetInteger(pname, out result1i);
output = pname + ": " + result1i;
break;
case eType.IntEnum:
GL.GetInteger(pname, out result1i);
output = pname + ": " + (All)result1i;
break;
case eType.IntArray2:
GL.GetInteger(pname, result2i);
output = pname + ": ( " + result2i[0] + ", " + result2i[1] + " )";
break;
case eType.IntArray4:
GL.GetInteger(pname, result4i);
output = pname + ": ( " + result4i[0] + ", " + result4i[1] + " ) ( " + result4i[2] + ", " + result4i[3] + " )";
break;
case eType.Float:
GL.GetFloat(pname, out result1f);
output = pname + ": " + result1f;
break;
case eType.FloatArray2:
GL.GetFloat(pname, out result2f);
output = pname + ": ( " + result2f.X + ", " + result2f.Y + " )";
break;
case eType.FloatArray4:
GL.GetFloat(pname, out result4f);
output = pname + ": ( " + result4f.X + ", " + result4f.Y + ", " + result4f.Z + ", " + result4f.W + " )";
break;
default: throw new NotImplementedException();
}
ErrorCode err = GL.GetError();
if (err != ErrorCode.NoError)
Trace.WriteLine("Unsupported Token: " + pname);
else
Trace.WriteLine(output);
}
#endregion GL.Get* Helper
/// <summary>Load resources here.</summary>
/// <param name="e">Not used.</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.ClearColor(System.Drawing.Color.MidnightBlue);
GL.Enable(EnableCap.DepthTest);
// returns 0 formats, driver broken?
/*
int CompressedTextureFormatCount;
GL.GetInteger(GetPName.NumCompressedTextureFormats, out CompressedTextureFormatCount);
if (CompressedTextureFormatCount > 0)
{
int[] CompressedTextureFormats = new int[CompressedTextureFormatCount];
GL.GetInteger(GetPName.CompressedTextureFormats, CompressedTextureFormats);
Trace.WriteLine("Supported compressed Texture formats:");
for (int i = 0; i < CompressedTextureFormats.Length; i++)
Trace.Write((All)CompressedTextureFormats[i] + ", ");
}
*/
string Renderer = GL.GetString(StringName.Renderer);
string GLSLang = GL.GetString(StringName.ShadingLanguageVersion);
string Vendor = GL.GetString(StringName.Vendor);
string Version = GL.GetString(StringName.Version);
string ExtensionsRaw = GL.GetString(StringName.Extensions);
string[] splitter = new string[] { " " };
string[] Extensions = ExtensionsRaw.Split(splitter, StringSplitOptions.None);
Trace.WriteLine("Vendor: " + Vendor);
Trace.WriteLine("Renderer: " + Renderer);
Trace.WriteLine("GL Version: " + Version);
Analyze(GetPName.MajorVersion, eType.Int);
Analyze(GetPName.MinorVersion, eType.Int);
Trace.WriteLine("GLSL Version: " + GLSLang);
Trace.WriteLine("Extensions: ");
for (int i = 0; i < Extensions.Length; i++)
Trace.WriteLine(Extensions[i]);
Trace.WriteLine("--- Framebuffer ---");
Analyze(GetPName.Doublebuffer, eType.Boolean);
Analyze(GetPName.MaxColorAttachments, eType.Int);
Analyze(GetPName.MaxDrawBuffers, eType.Int);
Analyze(GetPName.AuxBuffers, eType.Int);
Analyze(GetPName.DrawBuffer, eType.IntEnum);
Analyze(GetPName.MaxSamples, eType.Int);
Analyze(GetPName.MaxViewportDims, eType.IntArray2);
Analyze(GetPName.Viewport, eType.IntArray4);
Trace.WriteLine("--- Framebuffer channels ---");
Analyze(GetPName.RedBits, eType.Int);
Analyze(GetPName.GreenBits, eType.Int);
Analyze(GetPName.BlueBits, eType.Int);
Analyze(GetPName.AlphaBits, eType.Int);
Analyze(GetPName.DepthBits, eType.Int);
Analyze(GetPName.StencilBits, eType.Int);
Analyze(GetPName.AccumRedBits, eType.Int);
Analyze(GetPName.AccumGreenBits, eType.Int);
Analyze(GetPName.AccumBlueBits, eType.Int);
Analyze(GetPName.AccumAlphaBits, eType.Int);
Trace.WriteLine("--- Textures ---");
Analyze(GetPName.MaxCombinedTextureImageUnits, eType.Int);
Analyze(GetPName.MaxVertexTextureImageUnits, eType.Int);
Analyze(GetPName.MaxTextureImageUnits, eType.Int);
Analyze(GetPName.MaxTextureUnits, eType.Int);
Analyze(GetPName.MaxTextureSize, eType.Int);
Analyze(GetPName.Max3DTextureSize, eType.Int);
Analyze(GetPName.MaxCubeMapTextureSize, eType.Int);
Analyze(GetPName.MaxRenderbufferSize, eType.Int);
Analyze(GetPName.MaxTextureLodBias, eType.Int);
Queue<TexFormat> Supported = new Queue<TexFormat>();
Queue<TexFormat> Unsupported = new Queue<TexFormat>();
uint DummyTexture;
foreach (TexFormat t in TextureFormats)
{
GL.GenTextures(1, out DummyTexture);
GL.BindTexture(TextureTarget.Texture2D, DummyTexture);
GL.TexImage2D(TextureTarget.Texture2D, 0, t.pif, 4, 4, 0, t.pf, t.pt, IntPtr.Zero);
if (GL.GetError() == ErrorCode.NoError)
Supported.Enqueue(t);
else
Unsupported.Enqueue(t);
GL.DeleteTextures(1, ref DummyTexture);
}
GL.BindTexture(TextureTarget.Texture2D, 0);
Trace.WriteLine("--- UN-supported Texture formats ---");
while (Unsupported.Count > 0)
{
TexFormat tex = Unsupported.Dequeue();
Trace.Write((All)tex.pif+", ");
}
Trace.WriteLine( " " );
Trace.WriteLine("--- SUPPORTED Texture formats ---");
while (Supported.Count > 0)
{
TexFormat tex = Supported.Dequeue();
Trace.WriteLine((All)tex.pif+" " +tex.pf + " "+tex.pt);
}
Trace.WriteLine(" ");
Trace.WriteLine("--- Point&Line volumes ---");
Analyze(GetPName.AliasedPointSizeRange, eType.FloatArray2);
Analyze(GetPName.PointSizeMin, eType.Float);
Analyze(GetPName.PointSizeMax, eType.Float);
Analyze(GetPName.PointSizeGranularity, eType.Float);
Analyze(GetPName.PointSizeRange, eType.FloatArray2);
Analyze(GetPName.AliasedLineWidthRange, eType.FloatArray2);
Analyze(GetPName.LineWidthGranularity, eType.Float);
Analyze(GetPName.LineWidthRange, eType.FloatArray2);
Trace.WriteLine("--- VBO ---");
Analyze(GetPName.MaxElementsIndices, eType.Int);
Analyze(GetPName.MaxElementsVertices, eType.Int);
Analyze(GetPName.MaxVertexAttribs, eType.Int);
Trace.WriteLine("--- GLSL ---");
Analyze(GetPName.MaxCombinedFragmentUniformComponents, eType.Int);
Analyze(GetPName.MaxCombinedGeometryUniformComponents, eType.Int);
Analyze(GetPName.MaxCombinedVertexUniformComponents, eType.Int);
Analyze(GetPName.MaxFragmentUniformComponents, eType.Int);
Analyze(GetPName.MaxVertexUniformComponents, eType.Int);
Analyze(GetPName.MaxCombinedUniformBlocks, eType.Int);
Analyze(GetPName.MaxFragmentUniformBlocks, eType.Int);
Analyze(GetPName.MaxGeometryUniformBlocks, eType.Int);
Analyze(GetPName.MaxVertexUniformBlocks, eType.Int);
Analyze(GetPName.MaxUniformBlockSize, eType.Int);
Analyze(GetPName.MaxUniformBufferBindings, eType.Int);
Analyze(GetPName.MaxVaryingFloats, eType.Int);
Trace.WriteLine("--- Transform Feedback ---");
Analyze(GetPName.MaxTransformFeedbackInterleavedComponents, eType.Int);
Analyze(GetPName.MaxTransformFeedbackSeparateAttribs, eType.Int);
Analyze(GetPName.MaxTransformFeedbackSeparateComponents, eType.Int);
Trace.WriteLine("--- Fixed-Func Stacks, GL.Push* and GL.Pop* ---");
Analyze(GetPName.MaxClientAttribStackDepth, eType.Int);
Analyze(GetPName.MaxAttribStackDepth, eType.Int);
Analyze(GetPName.MaxProjectionStackDepth, eType.Int);
Analyze(GetPName.MaxModelviewStackDepth, eType.Int);
Analyze(GetPName.MaxTextureStackDepth, eType.Int);
Analyze(GetPName.MaxNameStackDepth, eType.Int);
Trace.WriteLine("--- Fixed-Func misc. stuff ---");
Analyze(GetPName.MaxEvalOrder, eType.Int);
Analyze(GetPName.MaxClipPlanes, eType.Int);
Analyze(GetPName.MaxArrayTextureLayers, eType.Int);
Analyze(GetPName.MaxListNesting, eType.Int);
Analyze(GetPName.MaxLights, eType.Int);
Analyze(GetPName.MaxTextureCoords, eType.Int);
this.Exit();
}
/// <summary>
/// Called when your window is resized. Set your viewport here. It is also
/// a good place to set up your projection matrix (which probably changes
/// along when the aspect ratio of your window).
/// </summary>
/// <param name="e">Not used.</param>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GL.Viewport(ClientRectangle);
}
/// <summary>
/// Called when it is time to setup the next frame. Add you game logic here.
/// </summary>
/// <param name="e">Contains timing information for framerate independent logic.</param>
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (Keyboard[Key.Escape])
Exit();
}
/// <summary>
/// Called when it is time to render the next frame. Add your rendering code here.
/// </summary>
/// <param name="e">Contains timing information.</param>
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// The 'using' idiom guarantees proper resource cleanup.
// We request 30 UpdateFrame events per second, and unlimited
// RenderFrame events (as fast as the computer can handle).
using (GLDiagnostics game = new GLDiagnostics())
{
game.Run(10.0);
}
}
}
}

Binary file not shown.

View file

@ -57,8 +57,8 @@ namespace Examples.Tutorial
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
// Setup VBO state
GL.EnableClientState(EnableCap.ColorArray);
GL.EnableClientState(EnableCap.VertexArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.EnableClientState(ArrayCap.VertexArray);
GL.GenBuffers(1, out VBOHandle);

View file

@ -730,9 +730,9 @@ namespace Examples.Tutorial
//GL.Arb.DrawArraysInstanced(BeginMode.Triangles, 0, cubeData.Length/8, 1);
GL.DrawArrays(BeginMode.Triangles, 0, cubeData.Length / (vboCubeStride / sizeof(float)));
GL.DisableClientState(EnableCap.VertexArray);
GL.DisableClientState(EnableCap.NormalArray);
GL.DisableClientState(EnableCap.TextureCoordArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
}
void renderSphereVBO()
@ -753,9 +753,9 @@ namespace Examples.Tutorial
//GL.Arb.DrawArraysInstanced(BeginMode.Triangles, 0, cubeData.Length/8, 1);
//GL.DrawArrays(BeginMode.Triangles, 0, sphereData.Length / (vboSphereStride / sizeof(float)));
GL.DisableClientState(EnableCap.VertexArray);
GL.DisableClientState(EnableCap.NormalArray);
GL.DisableClientState(EnableCap.TextureCoordArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
}
void renderCubemap()

View file

@ -261,8 +261,8 @@ namespace Examples.Tutorial
//GL.DrawArrays(GL.Enums.BeginMode.POINTS, 0, shape.Vertices.Length);
GL.DisableClientState(EnableCap.VertexArray);
GL.DisableClientState(EnableCap.ColorArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.ColorArray);
//int error = GL.GetError();

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -80,6 +80,10 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -143,6 +147,10 @@
<Compile Include="ExampleInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="OpenGL\1.x\Anaglyph.cs" />
<Compile Include="OpenGL\1.x\OpenGLDiagnostics.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="SamplesTreeViewSorter.cs">
<SubType>Code</SubType>
</Compile>
@ -543,6 +551,8 @@
<None Include="Data\Audio\the_ring_that_fell.wav">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="OpenGL\1.x\OpenGLDiagnostics.rtf" />
<EmbeddedResource Include="OpenGL\1.x\Anaglyph.rtf" />
<None Include="Resources\App.ico">
</None>
<None Include="..\OpenTK\OpenTK.dll.config">

View file

@ -66,7 +66,9 @@ namespace Examples.WinForms
void glControl_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F12)
glControl.GrabScreenshot().Save("screenshot.png");
{
GrabScreenshot().Save("screenshot.png");
}
}
#endregion
@ -204,6 +206,23 @@ namespace Examples.WinForms
#endregion
#region private void GrabScreenshot()
Bitmap GrabScreenshot()
{
Bitmap bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
System.Drawing.Imaging.BitmapData data =
bmp.LockBits(this.ClientRectangle, System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
GL.ReadPixels(0, 0, this.ClientSize.Width, this.ClientSize.Height, PixelFormat.Bgr, PixelType.UnsignedByte,
data.Scan0);
bmp.UnlockBits(data);
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmp;
}
#endregion
#region public static void Main()
/// <summary>

View file

@ -1,44 +1,46 @@
// This code is in the Public Domain. It is provided "as is"
// without express or implied warranty of any kind.
using System;
using System.Diagnostics;
using System.Reflection;
using OpenTK;
namespace Examples.Tests
{
struct Simple { public int Value; }
struct Generic<T> { public T Value; }
enum Enum { First, Second }
struct Complex { public Simple Value; }
struct Complex<T> { public Generic<T> Value; }
struct Complex2 { public Enum Value; }
struct Complex3 { public Class Value; }
struct Complex4 : Interface { public Class Value; }
class Class { public int Value; }
class Class<T> { public T Value; }
interface Interface { }
[Example("Blittable Value Types", ExampleCategory.OpenTK, "Test", Documentation="BlittableValueTypes")]
public class BlittableValueTypes
{
public static void Main()
{
TestType(new Simple());
TestType(new Generic<Simple>());
TestType(new Generic<Enum>());
TestType(new Complex());
TestType(new Complex<Enum>());
TestType(new Complex2());
TestType(new Complex3());
TestType(new Complex4());
TestType(new Class());
TestType(new Class<Simple>());
}
// Tests whether specified type is blittable and prints its marshalled size if so.
static void TestType<T>(T instance)
// without express or implied warranty of any kind.
using System;
using System.Diagnostics;
using System.Reflection;
using OpenTK;
#pragma warning disable 0649 // Do not warn about unitialized fields, this is on purpose
namespace Examples.Tests
{
struct Simple { public int Value; }
struct Generic<T> { public T Value; }
enum Enum { First, Second }
struct Complex { public Simple Value; }
struct Complex<T> { public Generic<T> Value; }
struct Complex2 { public Enum Value; }
struct Complex3 { public Class Value; }
struct Complex4 : Interface { public Class Value; }
class Class { public int Value; }
class Class<T> { public T Value; }
interface Interface { }
[Example("Blittable Value Types", ExampleCategory.OpenTK, "Test", Documentation="BlittableValueTypes")]
public class BlittableValueTypes
{
public static void Main()
{
TestType(new Simple());
TestType(new Generic<Simple>());
TestType(new Generic<Enum>());
TestType(new Complex());
TestType(new Complex<Enum>());
TestType(new Complex2());
TestType(new Complex3());
TestType(new Complex4());
TestType(new Class());
TestType(new Class<Simple>());
}
// Tests whether specified type is blittable and prints its marshalled size if so.
static void TestType<T>(T instance)
{
PrintType<T>();
@ -52,9 +54,9 @@ namespace Examples.Tests
catch (Exception e)
{
Trace.Write(String.Format("({0})", e.GetType().Name));
}
Trace.WriteLine("");
}
Trace.WriteLine("");
}
// Prints a simple description for the type.
@ -71,6 +73,6 @@ namespace Examples.Tests
Trace.Write(typename.Substring(typename.LastIndexOf('.') + 1));
Trace.Write(" } ");
}
}
}
}
}
}

View file

@ -14,15 +14,17 @@ using OpenTK.Input;
namespace Examples.Tests
{
[Example("GameWindow states", ExampleCategory.OpenTK, "Test", Documentation = "GameWindowStates")]
[Example("GameWindow States", ExampleCategory.OpenTK, "GameWindow", 4, Documentation = "GameWindowStates")]
public class GameWindowStates : GameWindow
{
static readonly Font TextFont = new Font(FontFamily.GenericSansSerif, 12);
static readonly Font TextFont = new Font(FontFamily.GenericSansSerif, 11);
Bitmap TextBitmap = new Bitmap(512, 512);
int texture;
bool mouse_in_window = false;
bool viewport_changed = true;
bool refresh_text = true;
MouseState mouse, mouse_old;
KeyboardState keyboard, keyboard_old;
public GameWindowStates()
: base(800, 600)
@ -38,14 +40,22 @@ namespace Examples.Tests
Resize += delegate { refresh_text = true; };
WindowBorderChanged += delegate { refresh_text = true; };
WindowStateChanged += delegate { refresh_text = true; };
Mouse.Move += delegate { refresh_text = true; };
FocusedChanged += delegate { refresh_text = true; };
Mouse.Move += MouseMoveHandler;
Mouse.ButtonDown += MouseButtonHandler;
Mouse.ButtonUp += MouseButtonHandler;
}
void KeyDownHandler(object sender, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
case OpenTK.Input.Key.Escape: this.Exit(); break;
case OpenTK.Input.Key.Escape:
if (!CursorVisible)
CursorVisible = true;
else
Exit();
break;
case Key.Number1: WindowState = WindowState.Normal; break;
case Key.Number2: WindowState = WindowState.Maximized; break;
@ -68,7 +78,22 @@ namespace Examples.Tests
case Key.Minus: Size -= new Size(16, 16); break;
}
}
void MouseMoveHandler(object sender, MouseMoveEventArgs e)
{
refresh_text = true;
}
void MouseButtonHandler(object sender, MouseButtonEventArgs e)
{
refresh_text = true;
if (e.Button == MouseButton.Left && e.IsPressed)
{
CursorVisible = false;
}
}
static int Clamp(int val, int min, int max)
{
return val > max ? max : val < min ? min : val;
@ -79,8 +104,58 @@ namespace Examples.Tests
gfx.DrawString(str, TextFont, Brushes.White, new PointF(0, line * TextFont.Height));
}
static void DrawString(Graphics gfx, string str, int line, float offset)
{
gfx.DrawString(str, TextFont, Brushes.White, new PointF(offset, line * TextFont.Height));
}
static void DrawKeyboard(Graphics gfx, KeyboardState keyboard, int line)
{
const string str = "Keys pressed:";
float space = gfx.MeasureString(" ", TextFont).Width;
float offset = gfx.MeasureString(str, TextFont).Width + space;
DrawString(gfx, str, line);
for (int i = 0; i < (int)Key.LastKey; i++)
{
Key k = (Key)i;
if (keyboard[k])
{
string key = k.ToString();
DrawString(gfx, key, line, offset);
offset += gfx.MeasureString(key, TextFont).Width + space;
}
}
}
static void DrawMouse(Graphics gfx, MouseState mouse, int line)
{
const string str = "Buttons pressed:";
float space = gfx.MeasureString(" ", TextFont).Width;
float offset = gfx.MeasureString(str, TextFont).Width + space;
DrawString(gfx, str, line);
for (int i = 0; i < (int)MouseButton.LastButton; i++)
{
MouseButton b = (MouseButton)i;
if (mouse[b])
{
string button = b.ToString();
DrawString(gfx, button, line, offset);
offset += gfx.MeasureString(button, TextFont).Width + space;
}
}
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
mouse = OpenTK.Input.Mouse.GetState();
if (mouse != mouse_old)
refresh_text = true;
mouse_old = mouse;
keyboard = OpenTK.Input.Keyboard.GetState();
if (keyboard != keyboard_old)
refresh_text = true;
keyboard_old = keyboard;
if (refresh_text)
{
refresh_text = false;
@ -89,18 +164,22 @@ namespace Examples.Tests
{
int line = 0;
gfx.Clear(Color.MidnightBlue);
gfx.Clear(Color.Black);
gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
DrawString(gfx, String.Format("[1 - 4]: change WindowState (current: {0}).", this.WindowState), line++);
DrawString(gfx, String.Format("[5 - 7]: change WindowBorder (current: {0}).", this.WindowBorder), line++);
DrawString(gfx, String.Format("Focused: {0}.", this.Focused), line++);
DrawString(gfx, String.Format("Mouse {0} window.", mouse_in_window ? "inside" : "outside of"), line++);
DrawString(gfx, String.Format("Mouse position: {0}", new Vector3(Mouse.X, Mouse.Y, Mouse.Wheel)), line++);
DrawString(gfx, String.Format("Mouse visible: {0}", CursorVisible), line++);
DrawString(gfx, String.Format("Mouse position (absolute): {0}", new Vector3(Mouse.X, Mouse.Y, Mouse.Wheel)), line++);
DrawString(gfx, String.Format("Mouse position (relative): {0}", new Vector3(mouse.X, mouse.Y, mouse.WheelPrecise)), line++);
DrawString(gfx, String.Format("Window.Bounds: {0}", Bounds), line++);
DrawString(gfx, String.Format("Window.Location: {0}, Size: {1}", Location, Size), line++);
DrawString(gfx, String.Format("Window.{{X={0}, Y={1}, Width={2}, Height={3}}}", X, Y, Width, Height), line++);
DrawString(gfx, String.Format("Window.ClientRectangle: {0}", ClientRectangle), line++);
DrawKeyboard(gfx, keyboard, line++);
DrawMouse(gfx, mouse, line++);
}
}
@ -120,6 +199,8 @@ namespace Examples.Tests
GL.ClearColor(Color.MidnightBlue);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcColor);
texture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture);

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -76,6 +76,10 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

View file

@ -1274,13 +1274,36 @@ namespace OpenTK.Audio.OpenAL
/// <param name="buffers">Pointer to an array of uint values which will store the names of the new buffers.</param>
[CLSCompliant(false)]
[DllImport(AL.Lib, EntryPoint = "alGenBuffers", ExactSpelling = true, CallingConvention = AL.Style), SuppressUnmanagedCodeSecurity]
public static extern void GenBuffers(int n, out uint buffers);
unsafe public static extern void GenBuffers(int n, [Out] int* buffers);
/// <summary>This function generates one or more buffers, which contain audio buffer (see AL.BufferData). References to buffers are uint values, which are used wherever a buffer reference is needed (in calls such as AL.DeleteBuffers, AL.Source with parameter ALSourcei, AL.SourceQueueBuffers, and AL.SourceUnqueueBuffers).</summary>
/// <param name="n">The number of buffers to be generated.</param>
/// <param name="buffers">Pointer to an array of uint values which will store the names of the new buffers.</param>
[DllImport(AL.Lib, EntryPoint = "alGenBuffers", ExactSpelling = true, CallingConvention = AL.Style), SuppressUnmanagedCodeSecurity]
public static extern void GenBuffers(int n, out int buffers);
[CLSCompliant(false)]
public static void GenBuffers(int n, out uint buffers)
{
unsafe
{
fixed (uint* pbuffers = &buffers)
{
GenBuffers(n, pbuffers);
}
}
}
/// <summary>This function generates one or more buffers, which contain audio buffer (see AL.BufferData). References to buffers are uint values, which are used wherever a buffer reference is needed (in calls such as AL.DeleteBuffers, AL.Source with parameter ALSourcei, AL.SourceQueueBuffers, and AL.SourceUnqueueBuffers).</summary>
/// <param name="n">The number of buffers to be generated.</param>
/// <param name="buffers">Pointer to an array of uint values which will store the names of the new buffers.</param>
public static void GenBuffers(int n, out int buffers)
{
unsafe
{
fixed (int* pbuffers = &buffers)
{
GenBuffers(n, pbuffers);
}
}
}
/// <summary>This function generates one or more buffers, which contain audio data (see AL.BufferData). References to buffers are uint values, which are used wherever a buffer reference is needed (in calls such as AL.DeleteBuffers, AL.Source with parameter ALSourcei, AL.SourceQueueBuffers, and AL.SourceUnqueueBuffers).</summary>
/// <param name="n">The number of buffers to be generated.</param>
@ -1326,13 +1349,36 @@ namespace OpenTK.Audio.OpenAL
/// <param name="buffers">Pointer to an array of buffer names identifying the buffers to be deleted.</param>
[CLSCompliant(false)]
[DllImport(AL.Lib, EntryPoint = "alDeleteBuffers", ExactSpelling = true, CallingConvention = AL.Style), SuppressUnmanagedCodeSecurity()]
public static extern void DeleteBuffers(int n, [In] ref uint buffers);
unsafe public static extern void DeleteBuffers(int n, [In] int* buffers);
/// <summary>This function deletes one or more buffers, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary>
/// <param name="n">The number of buffers to be deleted.</param>
/// <param name="buffers">Pointer to an array of buffer names identifying the buffers to be deleted.</param>
[DllImport(AL.Lib, EntryPoint = "alDeleteBuffers", ExactSpelling = true, CallingConvention = AL.Style), SuppressUnmanagedCodeSecurity()]
public static extern void DeleteBuffers(int n, [In] ref int buffers);
[CLSCompliant(false)]
public static void DeleteBuffers(int n, [In] ref uint buffers)
{
unsafe
{
fixed (uint* pbuffers = &buffers)
{
DeleteBuffers(n, pbuffers);
}
}
}
/// <summary>This function deletes one or more buffers, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary>
/// <param name="n">The number of buffers to be deleted.</param>
/// <param name="buffers">Pointer to an array of buffer names identifying the buffers to be deleted.</param>
public static void DeleteBuffers(int n, [In] ref int buffers)
{
unsafe
{
fixed (int* pbuffers = &buffers)
{
DeleteBuffers(n, pbuffers);
}
}
}
/// <summary>This function deletes one buffer only, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary>
/// <param name="buffers">Pointer to a buffer name identifying the buffer to be deleted.</param>

View file

@ -1,16 +1,33 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK team.
* This notice may not be removed.
* See license.txt for licensing detailed licensing details.
*/
#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.Text;
using System.Diagnostics;
using System.Threading;
using System.Drawing;
namespace OpenTK
@ -21,23 +38,19 @@ namespace OpenTK
/// </summary>
public class DisplayDevice
{
// TODO: Add support for refresh rate queries and switches.
// TODO: Check whether bits_per_pixel works correctly under Mono/X11.
// 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.
// TODO: Mono does not support System.Windows.Forms.Screen.BitsPerPixel -- find workaround!
#region --- Fields ---
#region Fields
bool primary;
Rectangle bounds;
DisplayResolution current_resolution = new DisplayResolution(), original_resolution;
List<DisplayResolution> available_resolutions = new List<DisplayResolution>();
IList<DisplayResolution> available_resolutions_readonly;
bool primary;
internal object Id; // A platform-specific id for this monitor
Rectangle bounds;
static readonly List<DisplayDevice> available_displays = new List<DisplayDevice>();
static readonly IList<DisplayDevice> available_displays_readonly;
static readonly object display_lock = new object();
static DisplayDevice primary_display;
@ -45,26 +58,21 @@ namespace OpenTK
#endregion
#region --- Constructors ---
#region Constructors
static DisplayDevice()
{
implementation = Platform.Factory.Default.CreateDisplayDeviceDriver();
available_displays_readonly = available_displays.AsReadOnly();
}
internal DisplayDevice()
{
lock (display_lock)
{
available_displays.Add(this);
}
available_resolutions_readonly = available_resolutions.AsReadOnly();
}
internal DisplayDevice(DisplayResolution currentResolution, bool primary,
IEnumerable<DisplayResolution> availableResolutions, Rectangle bounds)
IEnumerable<DisplayResolution> availableResolutions, Rectangle bounds,
object id)
: this()
{
#warning "Consolidate current resolution with bounds? Can they fall out of sync right now?"
@ -72,9 +80,7 @@ namespace OpenTK
IsPrimary = primary;
this.available_resolutions.AddRange(availableResolutions);
this.bounds = bounds == Rectangle.Empty ? currentResolution.Bounds : bounds;
Debug.Print("DisplayDevice {0} ({1}) supports {2} resolutions.",
available_displays.Count, primary ? "primary" : "secondary", available_resolutions.Count);
this.Id = id;
}
#endregion
@ -280,10 +286,23 @@ namespace OpenTK
/// <summary>
/// Gets the list of available <see cref="DisplayDevice"/> objects.
/// This function allocates memory.
/// </summary>
[Obsolete("Use GetDisplay(DisplayIndex) instead.")]
public static IList<DisplayDevice> AvailableDisplays
{
get { return available_displays_readonly; }
get
{
List<DisplayDevice> displays = new List<DisplayDevice>();
for (int i = 0; i < 6; i++)
{
DisplayDevice dev = GetDisplay(DisplayIndex.First + i);
if (dev != null)
displays.Add(dev);
}
return displays.AsReadOnly();
}
}
#endregion
@ -291,7 +310,24 @@ namespace OpenTK
#region public static DisplayDevice Default
/// <summary>Gets the default (primary) display of this system.</summary>
public static DisplayDevice Default { get { return primary_display; } }
public static DisplayDevice Default
{
get { return implementation.GetDisplay(DisplayIndex.Primary); }
}
#endregion
#region GetDisplay
/// <summary>
/// Gets the <see cref="DisplayDevice"/> for the specified <see cref="DeviceIndex"/>.
/// </summary>
/// <param name="index">The <see cref="DeviceIndex"/> that defines the desired display.</param>
/// <returns>A <see cref="DisplayDevice"/> or null, if no device corresponds to the specified index.</returns>
public static DisplayDevice GetDisplay(DisplayIndex index)
{
return implementation.GetDisplay(index);
}
#endregion

View file

@ -0,0 +1,72 @@
#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.Text;
namespace OpenTK
{
/// <summary>
/// Defines <see cref="DisplayDevice"/> indices.
/// </summary>
public enum DisplayIndex
{
/// <summary>
/// The first DisplayDevice.
/// </summary>
First = 0,
/// <summary>
/// The second DisplayDevice.
/// </summary>
Second,
/// <summary>
/// The third DisplayDevice.
/// </summary>
Third,
/// <summary>
/// The fourth DisplayDevice.
/// </summary>
Fourth,
/// <summary>
/// The fifth DisplayDevice.
/// </summary>
Fifth,
/// <summary>
/// The sixth DisplayDevice.
/// </summary>
Sixth,
/// <summary>
/// The default (primary) DisplayDevice.
/// </summary>
Primary = -1,
/// <summary>
/// The default (primary) DisplayDevice.
/// </summary>
Default = Primary,
}
}

View file

@ -316,7 +316,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnLoad(EventArgs e)
{
if (Load != null) Load(this, e);
Load(this, e);
}
#endregion
@ -329,7 +329,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnUnload(EventArgs e)
{
if (Unload != null) Unload(this, e);
Unload(this, e);
}
#endregion
@ -929,22 +929,22 @@ namespace OpenTK
/// <summary>
/// Occurs before the window is displayed for the first time.
/// </summary>
public event EventHandler<EventArgs> Load;
public event EventHandler<EventArgs> Load = delegate { };
/// <summary>
/// Occurs when it is time to render a frame.
/// </summary>
public event EventHandler<FrameEventArgs> RenderFrame;
public event EventHandler<FrameEventArgs> RenderFrame = delegate { };
/// <summary>
/// Occurs before the window is destroyed.
/// </summary>
public event EventHandler<EventArgs> Unload;
public event EventHandler<EventArgs> Unload = delegate { };
/// <summary>
/// Occurs when it is time to update a frame.
/// </summary>
public event EventHandler<FrameEventArgs> UpdateFrame;
public event EventHandler<FrameEventArgs> UpdateFrame = delegate { };
#endregion
@ -973,7 +973,7 @@ namespace OpenTK
/// </remarks>
protected virtual void OnRenderFrame(FrameEventArgs e)
{
if (RenderFrame != null) RenderFrame(this, e);
RenderFrame(this, e);
}
#endregion
@ -989,7 +989,7 @@ namespace OpenTK
/// </remarks>
protected virtual void OnUpdateFrame(FrameEventArgs e)
{
if (UpdateFrame != null) UpdateFrame(this, e);
UpdateFrame(this, e);
}
#endregion
@ -1006,6 +1006,15 @@ namespace OpenTK
#region OnResize
/// <summary>
/// Called when this window is resized.
/// </summary>
/// <param name="e">Not used.</param>
/// <remarks>
/// You will typically wish to update your viewport whenever
/// the window is resized. See the
/// <see cref="OpenTK.Graphics.OpenGL.GL.Viewport(int, int, int, int)"/> method.
/// </remarks>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);

View file

@ -1,9 +1,28 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#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;
@ -17,13 +36,13 @@ namespace OpenTK.Graphics
/// <para>A ColorFormat contains Red, Green, Blue and Alpha components that descibe
/// the allocated bits per pixel for the corresponding color.</para>
/// </remarks>
public struct ColorFormat
public struct ColorFormat : IComparable<ColorFormat>
{
byte red, green, blue, alpha;
bool isIndexed;
int bitsPerPixel;
#region --- Constructors ---
#region Constructors
/// <summary>
/// Constructs a new ColorFormat with the specified aggregate bits per pixel.
@ -96,7 +115,7 @@ namespace OpenTK.Graphics
#endregion
#region --- Public Methods ---
#region Public Members
/// <summary>Gets the bits per pixel for the Red channel.</summary>
public int Red { get { return red; } private set { red = (byte)value; } }
@ -111,9 +130,11 @@ namespace OpenTK.Graphics
/// <summary>Gets the sum of Red, Green, Blue and Alpha bits per pixel.</summary>
public int BitsPerPixel { get { return bitsPerPixel; } private set { bitsPerPixel = value; } }
public static readonly ColorFormat Empty = new ColorFormat(0);
#endregion
#region --- Operator Overloads ---
#region Operator Overloads
/// <summary>
/// Converts the specified bpp into a new ColorFormat.
@ -132,7 +153,32 @@ namespace OpenTK.Graphics
#endregion
#region --- Overrides ---
#region IComparable<ColorFormat> Members
/// <summary>
/// Compares two instances.
/// </summary>
/// <param name="other">The other instance.</param>
/// <returns>
/// Zero if this instance is equal to other;
/// a positive value if this instance is greater than other;
/// a negative value otherwise.
/// </returns>
public int CompareTo(ColorFormat other)
{
int result = BitsPerPixel.CompareTo(other.BitsPerPixel);
if (result != 0)
return result;
result = IsIndexed.CompareTo(other.IsIndexed);
if (result != 0)
return result;
result = Alpha.CompareTo(other.Alpha);
return result;
}
#endregion
#region Overrides
/// <summary>
/// Indicates whether this instance and a specified object are equal.
@ -176,6 +222,50 @@ namespace OpenTK.Graphics
return !(left == right);
}
/// <summary>
/// Compares two instances for inequality.
/// </summary>
/// <param name="left">The left operand.</param>
/// <param name="right">The right operand.</param>
/// <returns>True if left is greater than right; false otherwise.</returns>
public static bool operator >(ColorFormat left, ColorFormat right)
{
return left.CompareTo(right) > 0;
}
/// <summary>
/// Compares two instances for inequality.
/// </summary>
/// <param name="left">The left operand.</param>
/// <param name="right">The right operand.</param>
/// <returns>True if left is greater than or equal to right; false otherwise.</returns>
public static bool operator >=(ColorFormat left, ColorFormat right)
{
return left.CompareTo(right) >= 0;
}
/// <summary>
/// Compares two instances for inequality.
/// </summary>
/// <param name="left">The left operand.</param>
/// <param name="right">The right operand.</param>
/// <returns>True if left is less than right; false otherwise.</returns>
public static bool operator <(ColorFormat left, ColorFormat right)
{
return left.CompareTo(right) < 0;
}
/// <summary>
/// Compares two instances for inequality.
/// </summary>
/// <param name="left">The left operand.</param>
/// <param name="right">The right operand.</param>
/// <returns>True if left is less than or equal to right; false otherwise.</returns>
public static bool operator <=(ColorFormat left, ColorFormat right)
{
return left.CompareTo(right) <= 0;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>

View file

@ -1,9 +1,28 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#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;
@ -190,6 +209,39 @@ namespace OpenTK.Graphics
#endregion
#region Public Members
/// <summary>
/// Returns a <see cref="System.String"/> representing this instance.
/// </summary>
/// <returns>A <see cref="System.String"/> that contains a string representation of this instance.</returns>
public override string ToString()
{
return (this as IGraphicsContextInternal).Context.ToString();
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A System.Int32 with the hash code of this instance.</returns>
public override int GetHashCode()
{
return (this as IGraphicsContextInternal).Context.GetHashCode();
}
/// <summary>
/// Compares two instances.
/// </summary>
/// <param name="obj">The instance to compare to.</param>
/// <returns>True, if obj is equal to this instance; false otherwise.</returns>
public override bool Equals(object obj)
{
return (obj is GraphicsContext) &&
(this as IGraphicsContextInternal).Context == (obj as IGraphicsContextInternal).Context;
}
#endregion
#region Private Members
static IGraphicsContext FindSharedContext()

View file

@ -321,8 +321,8 @@ namespace OpenTK.Graphics
{
if (defaultMode == null)
{
Debug.Print("Creating default GraphicsMode ({0}, {1}, {2}, {3}, {4}, {5}, {6}).", DisplayDevice.Default.BitsPerPixel,
16, 0, 0, 0, 2, false);
Debug.Print("Creating default GraphicsMode ({0}, {1}, {2}, {3}, {4}, {5}, {6}).",
DisplayDevice.Default.BitsPerPixel, 16, 0, 0, 0, 2, false);
defaultMode = new GraphicsMode(DisplayDevice.Default.BitsPerPixel, 16, 0, 0, 0, 2, false);
}
return defaultMode;

View file

@ -0,0 +1,63 @@
#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.Text;
namespace OpenTK.Graphics
{
sealed class GraphicsModeComparer : IComparer<GraphicsMode>
{
#region IComparer<GraphicsMode> Members
public int Compare(GraphicsMode x, GraphicsMode y)
{
int result = x.ColorFormat.CompareTo(y.ColorFormat);
if (result != 0)
return result;
result = x.Depth.CompareTo(y.Depth);
if (result != 0)
return result;
result = x.Stencil.CompareTo(y.Stencil);
if (result != 0)
return result;
result = x.Samples.CompareTo(y.Samples);
if (result != 0)
return result;
result = x.Stereo.CompareTo(y.Stereo);
if (result != 0)
return result;
result = x.Buffers.CompareTo(y.Buffers);
if (result != 0)
return result;
return x.AccumulatorFormat.CompareTo(y.AccumulatorFormat);
}
#endregion
}
}

View file

@ -932,7 +932,7 @@ namespace OpenTK.Graphics.OpenGL
public static void TexEnv(TextureEnvTarget target, TextureEnvParameter pname, System.Drawing.Color color)
{
Color4 c = new Color4(color);
Color4 c = new Color4(color.R, color.G, color.B, color.A);
unsafe
{
TexEnv(target, pname, &c.R);

View file

@ -132,6 +132,16 @@ namespace OpenTK
[Obsolete]
OpenTK.Input.IInputDriver InputDriver { get; }
/// <summary>
/// Gets or sets a value, indicating whether the mouse cursor is visible.
/// </summary>
bool CursorVisible { get; set; }
// /// <summary>
// /// Gets or sets a value, indicating whether the mouse cursor is confined inside the window size.
// /// </summary>
// bool CursorGrabbed { get; set; }
/// <summary>
/// Closes this window.
/// </summary>
@ -219,10 +229,20 @@ namespace OpenTK
/// </summary>
event EventHandler<EventArgs> WindowStateChanged;
/// <summary>
/// Occurs whenever a keybord key is pressed.
/// </summary>
event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyDown;
/// <summary>
/// Occurs whenever a character is typed.
/// </summary>
event EventHandler<KeyPressEventArgs> KeyPress;
/// <summary>
/// Occurs whenever a keyboard key is released.
/// </summary>
event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyUp;
/// <summary>
/// Occurs whenever the mouse cursor leaves the window <see cref="Bounds"/>.
@ -241,10 +261,6 @@ namespace OpenTK
//event EventHandler<MouseEventArgs> MouseClick;
//event EventHandler<MouseEventArgs> MouseDoubleClick;
//event EventHandler<KeyEventArgs> KeyDown;
//event EventHandler<KeyEventArgs> KeyUp;
//event EventHandler<DragEventArgs> DragDrop;
//event EventHandler<DragEventArgs> DragEnter;
//event EventHandler<DragEventArgs> DragOver;

View file

@ -0,0 +1,46 @@
#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
namespace OpenTK.Input
{
/// <summary>
/// Enumerates possible mouse button states.
/// </summary>
public enum ButtonState
{
/// <summary>
/// Indicates that a mouse button is released.
/// </summary>
Released = 0,
/// <summary>
/// Indicates that a mouse button is pressed.
/// </summary>
Pressed = 1
}
}

View file

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Input
{
interface IGamePadDriver
{
}
}

View file

@ -0,0 +1,41 @@
#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.Text;
namespace OpenTK.Input
{
// Defines the interface for a 2nd generation input driver.
interface IInputDriver2
{
IMouseDriver2 MouseDriver { get; }
IKeyboardDriver2 KeyboardDriver { get; }
IGamePadDriver GamePadDriver { get; }
}
}

View file

@ -34,6 +34,7 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for JoystickDevice drivers.
/// </summary>
[Obsolete]
public interface IJoystickDriver
{
/// <summary>

View file

@ -13,6 +13,7 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for KeyboardDevice drivers.
/// </summary>
[Obsolete]
public interface IKeyboardDriver
{
/// <summary>

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Input
{
interface IKeyboardDriver2
{
/// <summary>
/// Retrieves the combined <see cref="OpenTK.Input.KeyboardState"/> for all keyboard devices.
/// </summary>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the combined state for all keyboard devices.</returns>
KeyboardState GetState();
/// <summary>
/// Retrieves the <see cref="OpenTK.Input.KeyboardState"/> for the specified keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
KeyboardState GetState(int index);
/// <summary>
/// Retrieves the device name for the keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="System.String"/> with the name of the specified device or <see cref="System.String.Empty"/>.</returns>
/// <remarks>
/// <para>If no device exists at the specified index, the return value is <see cref="System.String.Empty"/>.</para></remarks>
string GetDeviceName(int index);
}
}

View file

@ -13,6 +13,7 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for MouseDevice drivers.
/// </summary>
[Obsolete]
public interface IMouseDriver
{
/// <summary>

View file

@ -0,0 +1,40 @@
 #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.Text;
namespace OpenTK.Input
{
interface IMouseDriver2
{
MouseState GetState();
MouseState GetState(int index);
void SetPosition(double x, double y);
}
}

View file

@ -1,126 +0,0 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK.Input;
using OpenTK.Platform;
namespace OpenTK
{
internal class InputDriver : IInputDriver
{
private IInputDriver inputDriver;
#region --- Constructors ---
public InputDriver(GameWindow parent)
{
if (parent == null)
throw new ArgumentException("A valid window (IWindowInfo) must be specified to construct an InputDriver");
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32Windows:
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.WinCE:
if (Environment.OSVersion.Version.Major > 5 ||
(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1))
{
inputDriver = new OpenTK.Platform.Windows.WinRawInput((OpenTK.Platform.Windows.WinWindowInfo)parent.WindowInfo);
}
else
{
// Legacy or unknown windows version:
inputDriver = new OpenTK.Platform.Windows.WMInput((OpenTK.Platform.Windows.WinWindowInfo)parent.WindowInfo);
}
break;
case PlatformID.Unix:
// TODO: Input is currently handled asychronously by the driver in X11GLNative.
//inputDriver = new OpenTK.Platform.X11.X11Input(parent.WindowInfo);
break;
default:
throw new PlatformNotSupportedException(
"Input handling is not supported on the current platform. Please report the problem to http://opentk.sourceforge.net");
}
}
#endregion
#region --- IInputDriver Members ---
public void Poll()
{
inputDriver.Poll();
}
#endregion
#region --- IKeyboardDriver Members ---
public IList<KeyboardDevice> Keyboard
{
get { return inputDriver.Keyboard; }
}
#endregion
#region --- IMouseDriver Members ---
public IList<MouseDevice> Mouse
{
get { return inputDriver.Mouse; }
}
#endregion
#region --- IJoystickDriver Members ---
public IList<JoystickDevice> Joysticks
{
get { return inputDriver.Joysticks; }
}
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
{
inputDriver.Dispose();
}
disposed = true;
}
}
~InputDriver()
{
this.Dispose(false);
}
#endregion
}
}

View file

@ -38,41 +38,64 @@ namespace OpenTK.Input
{
#region Fields
//static IKeyboardDriver driver;
#endregion
#region Constructors
static Keyboard()
{
throw new NotImplementedException();
//driver = Platform.Factory.Default.CreateKeyboardDriver();
}
static readonly IKeyboardDriver2 driver =
Platform.Factory.Default.CreateKeyboardDriver();
static readonly object SyncRoot = new object();
#endregion
#region Public Members
/// <summary>
/// Retrieves the KeyboardState for the default keyboard device.
/// Retrieves the combined <see cref="OpenTK.Input.KeyboardState"/> for all keyboard devices.
/// </summary>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the combined state for all keyboard devices.</returns>
public static KeyboardState GetState()
{
return new KeyboardState();
lock (SyncRoot)
{
return driver.GetState();
}
}
/// <summary>
/// Retrieves the KeyboardState for the specified keyboard device.
/// Retrieves the <see cref="OpenTK.Input.KeyboardState"/> for the specified keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
public static KeyboardState GetState(int index)
{
return new KeyboardState();
if (index < 0)
throw new ArgumentOutOfRangeException("index");
lock (SyncRoot)
{
return driver.GetState(index);
}
}
#endregion
#if false
// Disabled until a correct, cross-platform API can be defined.
/// <summary>
/// Retrieves the device name for the keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="System.String"/> with the name of the specified device or <see cref="System.String.Empty"/>.</returns>
/// <remarks>
/// <para>If no device exists at the specified index, the return value is <see cref="System.String.Empty"/>.</para></remarks>
public static string GetDeviceName(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index");
lock (SyncRoot)
{
return driver.GetDeviceName(index);
}
}
#endif
#endregion
}
}

View file

@ -26,7 +26,7 @@
#endregion
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
namespace OpenTK.Input
@ -38,26 +38,42 @@ namespace OpenTK.Input
{
#region Fields
const int NumKeys = ((int)Key.LastKey + 16) / 32;
// Todo: The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
// Need to add a workaround using either ExplicitLayout or another trick.
//unsafe fixed int Keys[NumKeys];
#endregion
#region Constructors
// Allocate enough ints to store all keyboard keys
const int IntSize = sizeof(int);
const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
// The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
unsafe fixed int Keys[NumInts];
bool is_connected;
#endregion
#region Public Members
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the specified
/// <see cref="OpenTK.Input.Key"/> is pressed.
/// </summary>
/// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
/// <returns>True if key is pressed; false otherwise.</returns>
public bool this[Key key]
{
get { return IsKeyDown(key); }
internal set
{
if (value)
EnableBit((int)key);
else
DisableBit((int)key);
}
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this key is down.
/// </summary>
/// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
public bool IsKeyDown(Key key)
{
return ReadBit((int)key) != 0;
return ReadBit((int)key);
}
/// <summary>
@ -66,24 +82,178 @@ namespace OpenTK.Input
/// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
public bool IsKeyUp(Key key)
{
return ReadBit((int)key) == 0;
return !ReadBit((int)key);
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this keyboard
/// is connected.
/// </summary>
public bool IsConnected
{
get { return is_connected; }
internal set { is_connected = value; }
}
#if false
// Disabled until the correct cross-platform API can be determined.
public bool IsLedOn(KeyboardLeds led)
{
return false;
}
public bool IsLedOff(KeyboardLeds led)
{
return false;
}
#endif
/// <summary>
/// Checks whether two <see cref="KeyboardState" /> instances are equal.
/// </summary>
/// <param name="left">
/// A <see cref="KeyboardState"/> instance.
/// </param>
/// <param name="right">
/// A <see cref="KeyboardState"/> instance.
/// </param>
/// <returns>
/// True if both left is equal to right; false otherwise.
/// </returns>
public static bool operator ==(KeyboardState left, KeyboardState right)
{
return left.Equals(right);
}
/// <summary>
/// Checks whether two <see cref="KeyboardState" /> instances are not equal.
/// </summary>
/// <param name="left">
/// A <see cref="KeyboardState"/> instance.
/// </param>
/// <param name="right">
/// A <see cref="KeyboardState"/> instance.
/// </param>
/// <returns>
/// True if both left is not equal to right; false otherwise.
/// </returns>
public static bool operator !=(KeyboardState left, KeyboardState right)
{
return !left.Equals(right);
}
/// <summary>
/// Compares to an object instance for equality.
/// </summary>
/// <param name="obj">
/// The <see cref="System.Object"/> to compare to.
/// </param>
/// <returns>
/// True if this instance is equal to obj; false otherwise.
/// </returns>
public override bool Equals(object obj)
{
if (obj is KeyboardState)
{
return this == (KeyboardState)obj;
}
else
{
return false;
}
}
/// <summary>
/// Generates a hashcode for the current instance.
/// </summary>
/// <returns>
/// A <see cref="System.Int32"/> represting the hashcode for this instance.
/// </returns>
public override int GetHashCode()
{
unsafe
{
fixed (int* k = Keys)
{
int hashcode = 0;
for (int i = 0; i < NumInts; i++)
hashcode ^= (k + i)->GetHashCode();
return hashcode;
}
}
}
#endregion
#region Internal Members
internal int ReadBit(int offset)
internal bool ReadBit(int offset)
{
return 0;
//unsafe { return (Keys[(offset / 32)] & (1 << (offset % 32))); }
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* k = Keys)
{
return (*(k + int_offset) & (1 << bit_offset)) != 0u;
}
}
}
internal enum BitValue { Zero = 0, One = 1 }
internal void WriteBit(int offset, BitValue bit)
internal void EnableBit(int offset)
{
// Todo: this is completely broken.
//unsafe { Keys[offset / 32] = Keys[offset / 32] ^ (~(int)bit << (offset % 32)); }
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* k = Keys)
{
*(k + int_offset) |= 1 << bit_offset;
}
}
}
internal void DisableBit(int offset)
{
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* k = Keys)
{
*(k + int_offset) &= ~(1 << bit_offset);
}
}
}
internal void MergeBits(KeyboardState other)
{
unsafe
{
int* k2 = other.Keys;
fixed (int* k1 = Keys)
{
for (int i = 0; i < NumInts; i++)
*(k1 + i) |= *(k2 + i);
}
}
IsConnected |= other.IsConnected;
}
#endregion
#region Private Members
static void ValidateOffset(int offset)
{
if (offset < 0 || offset >= NumInts * IntSize)
throw new ArgumentOutOfRangeException("offset");
}
#endregion
@ -97,7 +267,17 @@ namespace OpenTK.Input
/// <returns>True, if both instances are equal; false otherwise.</returns>
public bool Equals(KeyboardState other)
{
throw new NotImplementedException();
bool equal = true;
unsafe
{
int* k2 = other.Keys;
fixed (int* k1 = Keys)
{
for (int i = 0; equal && i < NumInts; i++)
equal &= *(k1 + i) == *(k2 + i);
}
}
return equal;
}
#endregion

View file

@ -38,28 +38,57 @@ namespace OpenTK.Input
{
#region Fields
//static IMouseDriver driver;
#endregion
#region Constructors
static Mouse()
{
}
static readonly IMouseDriver2 driver =
Platform.Factory.Default.CreateMouseDriver();
static readonly object SyncRoot = new object();
#endregion
#region Public Members
/// <summary>
/// Retrieves the MouseState for the specified mouse device.
/// Retrieves the combined <see cref="OpenTK.Input.MouseState"/> for all specified mouse devices.
/// </summary>
/// <returns>A <see cref="OpenTK.Input.MouseState"/> structure containing the combined state of all mouse devices.</returns>
public static MouseState GetState()
{
lock (SyncRoot)
{
return driver.GetState();
}
}
/// <summary>
/// Retrieves the <see cref="OpenTK.Input.MouseState"/> for the specified mouse device.
/// </summary>
/// <param name="index">The index of the mouse device.</param>
/// <returns>A <see cref="OpenTK.Input.MouseState"/> structure containing the state of the mouse device.</returns>
/// <returns>A <see cref="OpenTK.Input.MouseState"/> structure containing the state for the specified mouse device.</returns>
public static MouseState GetState(int index)
{
throw new NotImplementedException();
if (index < 0)
throw new ArgumentOutOfRangeException("index");
lock (SyncRoot)
{
return driver.GetState(index);
}
}
/// <summary>
///Moves the mouse cursor to the specified screen position.
/// </summary>
/// <param name="x">
/// A <see cref="System.Double"/> that represents the absolute x position of the cursor in screen coordinates.
/// </param>
/// <param name="y">
/// A <see cref="System.Double"/> that represents the absolute y position of the cursor in screen coordinates.
/// </param>
public static void SetPosition(double x, double y)
{
lock (SyncRoot)
{
driver.SetPosition(x, y);
}
}
#endregion

View file

@ -36,10 +36,303 @@ namespace OpenTK.Input
/// </summary>
public struct MouseState : IEquatable<MouseState>
{
#region Constructors
#region Fields
internal MouseState(MouseButton[] buttons)
// Allocate enough ints to store all mouse buttons
const int IntSize = sizeof(int);
const int NumInts = ((int)MouseButton.LastButton + IntSize - 1) / IntSize;
// The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
unsafe fixed int Buttons[NumInts];
int x, y;
float wheel;
bool is_connected;
#endregion
#region Public Members
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the specified
/// <see cref="OpenTK.Input.MouseButton"/> is pressed.
/// </summary>
/// <param name="button">The <see cref="OpenTK.Input.MouseButton"/> to check.</param>
/// <returns>True if key is pressed; false otherwise.</returns>
public bool this[MouseButton button]
{
get { return IsButtonDown(button); }
internal set
{
if (value)
EnableBit((int)button);
else
DisableBit((int)button);
}
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this button is down.
/// </summary>
/// <param name="button">The <see cref="OpenTK.Input.MouseButton"/> to check.</param>
public bool IsButtonDown(MouseButton button)
{
return ReadBit((int)button);
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this button is up.
/// </summary>
/// <param name="button">The <see cref="OpenTK.Input.MouseButton"/> to check.</param>
public bool IsButtonUp(MouseButton button)
{
return !ReadBit((int)button);
}
/// <summary>
/// Gets the absolute wheel position in integer units.
/// To support high-precision mice, it is recommended to use <see cref="WheelPrecise"/> instead.
/// </summary>
public int Wheel
{
get { return (int)Math.Round(wheel, MidpointRounding.AwayFromZero); }
}
/// <summary>
/// Gets the absolute wheel position in floating-point units.
/// </summary>
public float WheelPrecise
{
get { return wheel; }
internal set
{
wheel = value;
}
}
/// <summary>
/// Gets an integer representing the absolute x position of the pointer, in window pixel coordinates.
/// </summary>
public int X
{
get { return x; }
internal set { x = value; }
}
/// <summary>
/// Gets an integer representing the absolute y position of the pointer, in window pixel coordinates.
/// </summary>
public int Y
{
get { return y; }
internal set { y = value; }
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the left mouse button is pressed.
/// This property is intended for XNA compatibility.
/// </summary>
public ButtonState LeftButton
{
get { return IsButtonDown(MouseButton.Left) ? ButtonState.Pressed : ButtonState.Released; }
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the middle mouse button is pressed.
/// This property is intended for XNA compatibility.
/// </summary>
public ButtonState MiddleButton
{
get { return IsButtonDown(MouseButton.Middle) ? ButtonState.Pressed : ButtonState.Released; }
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the right mouse button is pressed.
/// This property is intended for XNA compatibility.
/// </summary>
public ButtonState RightButton
{
get { return IsButtonDown(MouseButton.Right) ? ButtonState.Pressed : ButtonState.Released; }
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the first extra mouse button is pressed.
/// This property is intended for XNA compatibility.
/// </summary>
public ButtonState XButton1
{
get { return IsButtonDown(MouseButton.Button1) ? ButtonState.Pressed : ButtonState.Released; }
}
/// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether the second extra mouse button is pressed.
/// This property is intended for XNA compatibility.
/// </summary>
public ButtonState XButton2
{
get { return IsButtonDown(MouseButton.Button2) ? ButtonState.Pressed : ButtonState.Released; }
}
/// <summary>
/// Gets the absolute wheel position in integer units. This property is intended for XNA compatibility.
/// To support high-precision mice, it is recommended to use <see cref="WheelPrecise"/> instead.
/// </summary>
public int ScrollWheelValue
{
get { return Wheel; }
}
public bool IsConnected
{
get { return is_connected; }
internal set { is_connected = value; }
}
/// <summary>
/// Checks whether two <see cref="MouseState" /> instances are equal.
/// </summary>
/// <param name="left">
/// A <see cref="MouseState"/> instance.
/// </param>
/// <param name="right">
/// A <see cref="MouseState"/> instance.
/// </param>
/// <returns>
/// True if both left is equal to right; false otherwise.
/// </returns>
public static bool operator ==(MouseState left, MouseState right)
{
return left.Equals(right);
}
/// <summary>
/// Checks whether two <see cref="MouseState" /> instances are not equal.
/// </summary>
/// <param name="left">
/// A <see cref="MouseState"/> instance.
/// </param>
/// <param name="right">
/// A <see cref="MouseState"/> instance.
/// </param>
/// <returns>
/// True if both left is not equal to right; false otherwise.
/// </returns>
public static bool operator !=(MouseState left, MouseState right)
{
return !left.Equals(right);
}
/// <summary>
/// Compares to an object instance for equality.
/// </summary>
/// <param name="obj">
/// The <see cref="System.Object"/> to compare to.
/// </param>
/// <returns>
/// True if this instance is equal to obj; false otherwise.
/// </returns>
public override bool Equals(object obj)
{
if (obj is MouseState)
{
return this == (MouseState)obj;
}
else
{
return false;
}
}
/// <summary>
/// Generates a hashcode for the current instance.
/// </summary>
/// <returns>
/// A <see cref="System.Int32"/> represting the hashcode for this instance.
/// </returns>
public override int GetHashCode()
{
unsafe
{
fixed (int* b = Buttons)
{
return b->GetHashCode() ^ X.GetHashCode() ^ Y.GetHashCode() ^ WheelPrecise.GetHashCode();
}
}
}
#endregion
#region Internal Members
internal bool ReadBit(int offset)
{
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* b = Buttons)
{
return (*(b + int_offset) & (1 << bit_offset)) != 0u;
}
}
}
internal void EnableBit(int offset)
{
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* b = Buttons)
{
*(b + int_offset) |= 1 << bit_offset;
}
}
}
internal void DisableBit(int offset)
{
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
fixed (int* b = Buttons)
{
*(b + int_offset) &= ~(1 << bit_offset);
}
}
}
internal void MergeBits(MouseState other)
{
unsafe
{
int* b2 = other.Buttons;
fixed (int* b1 = Buttons)
{
for (int i = 0; i < NumInts; i++)
*(b1 + i) |= *(b2 + i);
}
WheelPrecise += other.WheelPrecise;
X += other.X;
Y += other.Y;
IsConnected |= other.IsConnected;
}
}
#endregion
#region Private Members
static void ValidateOffset(int offset)
{
if (offset < 0 || offset >= NumInts * IntSize)
throw new ArgumentOutOfRangeException("offset");
}
#endregion
@ -47,13 +340,24 @@ namespace OpenTK.Input
#region IEquatable<MouseState> Members
/// <summary>
/// Compares two MouseState instances for equality.
/// Compares two MouseState instances.
/// </summary>
/// <param name="other">The instance to compare to.</param>
/// <param name="other">The instance to compare two.</param>
/// <returns>True, if both instances are equal; false otherwise.</returns>
public bool Equals(MouseState other)
{
throw new NotImplementedException();
bool equal = true;
unsafe
{
int* b2 = other.Buttons;
fixed (int* b1 = Buttons)
{
for (int i = 0; equal && i < NumInts; i++)
equal &= *(b1 + i) == *(b2 + i);
}
equal &= X == other.X && Y == other.Y && WheelPrecise == other.WheelPrecise;
}
return equal;
}
#endregion

View file

@ -0,0 +1,49 @@
#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;
namespace OpenTK
{
// Simple equality comparer to allow IntPtrs as keys in dictionaries
// without causing boxing/garbage generation.
// Seriously, Microsoft, shouldn't this have been in the BCL out of the box?
class IntPtrEqualityComparer : IEqualityComparer<IntPtr>
{
public bool Equals(IntPtr x, IntPtr y)
{
return x == y;
}
public int GetHashCode(IntPtr obj)
{
return obj.GetHashCode();
}
}
}

View file

@ -45,8 +45,8 @@ namespace OpenTK
{
Left = topLeft.X;
Top = topLeft.Y;
Right = topLeft.X;
Bottom = topLeft.Y;
Right = bottomRight.X;
Bottom = bottomRight.Y;
}
/// <summary>

View file

@ -565,8 +565,6 @@ namespace OpenTK
throw new ArgumentOutOfRangeException("zNear");
if (zFar <= 0)
throw new ArgumentOutOfRangeException("zFar");
if (zNear >= zFar)
throw new ArgumentOutOfRangeException("zNear");
float yMax = zNear * (float)System.Math.Tan(0.5f * fovy);
float yMin = -yMax;

View file

@ -565,8 +565,6 @@ namespace OpenTK
throw new ArgumentOutOfRangeException("zNear");
if (zFar <= 0)
throw new ArgumentOutOfRangeException("zFar");
if (zNear >= zFar)
throw new ArgumentOutOfRangeException("zNear");
double yMax = zNear * System.Math.Tan(0.5 * fovy);
double yMin = -yMax;

View file

@ -50,6 +50,16 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector2(float value)
{
X = value;
Y = value;
}
/// <summary>
/// Constructs a new Vector2.
/// </summary>

View file

@ -69,6 +69,16 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector2d(double value)
{
X = value;
Y = value;
}
/// <summary>Constructs left vector with the given coordinates.</summary>
/// <param name="x">The X coordinate.</param>
/// <param name="y">The Y coordinate.</param>

View file

@ -46,6 +46,26 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector2h(Half value)
{
X = value;
Y = value;
}
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector2h(Single value)
{
X = new Half(value);
Y = new Half(value);
}
/// <summary>
/// The new Half2 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>

View file

@ -58,6 +58,17 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector3(float value)
{
X = value;
Y = value;
Z = value;
}
/// <summary>
/// Constructs a new Vector3.
/// </summary>
@ -1143,7 +1154,7 @@ namespace OpenTK
/// <param name="result">The transformed vector</param>
public static void TransformPerspective(ref Vector3 vec, ref Matrix4 mat, out Vector3 result)
{
Vector4 v = new Vector4(vec);
Vector4 v = new Vector4(vec, 1);
Vector4.Transform(ref v, ref mat, out v);
result.X = v.X / v.W;
result.Y = v.Y / v.W;

View file

@ -56,6 +56,17 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector3d(double value)
{
X = value;
Y = value;
Z = value;
}
/// <summary>
/// Constructs a new Vector3.
/// </summary>
@ -1141,7 +1152,7 @@ namespace OpenTK
/// <param name="result">The transformed vector</param>
public static void TransformPerspective(ref Vector3d vec, ref Matrix4d mat, out Vector3d result)
{
Vector4d v = new Vector4d(vec);
Vector4d v = new Vector4d(vec, 1);
Vector4d.Transform(ref v, ref mat, out v);
result.X = v.X / v.W;
result.Y = v.Y / v.W;
@ -1353,10 +1364,10 @@ namespace OpenTK
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector3))
if (!(obj is Vector3d))
return false;
return this.Equals((Vector3)obj);
return this.Equals((Vector3d)obj);
}
#endregion

View file

@ -51,6 +51,28 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector3h(Half value)
{
X = value;
Y = value;
Z = value;
}
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector3h(Single value)
{
X = new Half(value);
Y = new Half(value);
Z = new Half(value);
}
/// <summary>
/// The new Half3 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>

View file

@ -96,6 +96,18 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector4(float value)
{
X = value;
Y = value;
Z = value;
W = value;
}
/// <summary>
/// Constructs a new Vector4.
/// </summary>
@ -125,8 +137,10 @@ namespace OpenTK
/// <summary>
/// Constructs a new Vector4 from the given Vector3.
/// The w component is initialized to 0.
/// </summary>
/// <param name="v">The Vector3 to copy components from.</param>
/// <remarks><seealso cref="Vector4(Vector3, float)"/></remarks>
public Vector4(Vector3 v)
{
X = v.X;

View file

@ -94,6 +94,18 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector4d(double value)
{
X = value;
Y = value;
Z = value;
W = value;
}
/// <summary>
/// Constructs a new Vector4d.
/// </summary>
@ -123,8 +135,10 @@ namespace OpenTK
/// <summary>
/// Constructs a new Vector4d from the given Vector3d.
/// The w component is initialized to 0.
/// </summary>
/// <param name="v">The Vector3d to copy components from.</param>
/// <remarks><seealso cref="Vector4d(Vector3d, double)"/></remarks>
public Vector4d(Vector3d v)
{
X = v.X;

View file

@ -54,6 +54,30 @@ namespace OpenTK
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector4h(Half value)
{
X = value;
Y = value;
Z = value;
W = value;
}
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="value">The value that will initialize this instance.</param>
public Vector4h(Single value)
{
X = new Half(value);
Y = new Half(value);
Z = new Half(value);
W = new Half(value);
}
/// <summary>
/// The new Half4 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>

View file

@ -49,6 +49,8 @@ namespace OpenTK
private readonly INativeWindow implementation;
private bool disposed, events;
private bool cursor_visible = true;
private bool previous_cursor_visible = true;
#endregion
@ -541,6 +543,23 @@ namespace OpenTK
#endregion
#region CursorVisible
/// <summary>
/// Gets or sets a value indicating whether the mouse cursor is visible.
/// </summary>
public bool CursorVisible
{
get { return cursor_visible; }
set
{
cursor_visible = value;
implementation.CursorVisible = value;
}
}
#endregion
#endregion
#region Events
@ -548,72 +567,82 @@ namespace OpenTK
/// <summary>
/// Occurs after the window has closed.
/// </summary>
public event EventHandler<EventArgs> Closed;
public event EventHandler<EventArgs> Closed = delegate { };
/// <summary>
/// Occurs when the window is about to close.
/// </summary>
public event EventHandler<CancelEventArgs> Closing;
public event EventHandler<CancelEventArgs> Closing = delegate { };
/// <summary>
/// Occurs when the window is disposed.
/// </summary>
public event EventHandler<EventArgs> Disposed;
public event EventHandler<EventArgs> Disposed = delegate { };
/// <summary>
/// Occurs when the <see cref="Focused"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> FocusedChanged;
public event EventHandler<EventArgs> FocusedChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="Icon"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> IconChanged;
public event EventHandler<EventArgs> IconChanged = delegate { };
/// <summary>
/// Occurs whenever a keybord key is pressed.
/// </summary>
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyDown = delegate { };
/// <summary>
/// Occurs whenever a character is typed.
/// </summary>
public event EventHandler<KeyPressEventArgs> KeyPress;
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
/// <summary>
/// Occurs whenever a keyboard key is released.
/// </summary>
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyUp = delegate { };
/// <summary>
/// Occurs whenever the window is moved.
/// </summary>
public event EventHandler<EventArgs> Move;
public event EventHandler<EventArgs> Move = delegate { };
/// <summary>
/// Occurs whenever the mouse cursor enters the window <see cref="Bounds"/>.
/// </summary>
public event EventHandler<EventArgs> MouseEnter;
public event EventHandler<EventArgs> MouseEnter = delegate { };
/// <summary>
/// Occurs whenever the mouse cursor leaves the window <see cref="Bounds"/>.
/// </summary>
public event EventHandler<EventArgs> MouseLeave;
public event EventHandler<EventArgs> MouseLeave = delegate { };
/// <summary>
/// Occurs whenever the window is resized.
/// </summary>
public event EventHandler<EventArgs> Resize;
public event EventHandler<EventArgs> Resize = delegate { };
/// <summary>
/// Occurs when the <see cref="Title"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> TitleChanged;
public event EventHandler<EventArgs> TitleChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="Visible"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> VisibleChanged;
public event EventHandler<EventArgs> VisibleChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="WindowBorder"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> WindowBorderChanged;
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="WindowState"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> WindowStateChanged;
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
#endregion
@ -687,7 +716,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnClosed(EventArgs e)
{
if (Closed != null) Closed(this, e);
Closed(this, e);
}
#endregion
@ -702,7 +731,7 @@ namespace OpenTK
/// Set e.Cancel to true in order to stop the NativeWindow from closing.</param>
protected virtual void OnClosing(CancelEventArgs e)
{
if (Closing != null) Closing(this, e);
Closing(this, e);
}
#endregion
@ -715,7 +744,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnDisposed(EventArgs e)
{
if (Disposed != null) Disposed(this, e);
Disposed(this, e);
}
#endregion
@ -728,7 +757,21 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnFocusedChanged(EventArgs e)
{
if (FocusedChanged != null) FocusedChanged(this, e);
if (!Focused)
{
// Release cursor when losing focus, to ensure
// IDEs continue working as expected.
previous_cursor_visible = CursorVisible;
CursorVisible = true;
}
else if (!previous_cursor_visible)
{
// Make cursor invisible when focus is regained
// if cursor was invisible on previous focus loss.
previous_cursor_visible = true;
CursorVisible = false;
}
FocusedChanged(this, e);
}
#endregion
@ -741,7 +784,19 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnIconChanged(EventArgs e)
{
if (IconChanged != null) IconChanged(this, e);
IconChanged(this, e);
}
#endregion
#region OnKeyDown
/// <summary>
/// Occurs whenever a keybord key is pressed.
/// </summary>
protected virtual void OnKeyDown(KeyboardKeyEventArgs e)
{
KeyDown(this, e);
}
#endregion
@ -754,7 +809,20 @@ namespace OpenTK
/// <param name="e">The <see cref="OpenTK.KeyPressEventArgs"/> for this event.</param>
protected virtual void OnKeyPress(KeyPressEventArgs e)
{
if (KeyPress != null) KeyPress(this, e);
KeyPress(this, e);
}
#endregion
#region OnKeyUp
/// <summary>
/// Called when a keybord key is released.
/// </summary>
/// <param name="e">The <see cref="OpenTK.KeyboardKeyEventArgs"/> for this event.</param>
protected virtual void OnKeyUp(KeyboardKeyEventArgs e)
{
KeyUp(this, e);
}
#endregion
@ -767,7 +835,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnMove(EventArgs e)
{
if (Move != null) Move(this, e);
Move(this, e);
}
#endregion
@ -780,7 +848,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnMouseEnter(EventArgs e)
{
if (MouseEnter != null) MouseEnter(this, e);
MouseEnter(this, e);
}
#endregion
@ -793,7 +861,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnMouseLeave(EventArgs e)
{
if (MouseLeave != null) MouseLeave(this, e);
MouseLeave(this, e);
}
#endregion
@ -806,7 +874,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnResize(EventArgs e)
{
if (Resize != null) Resize(this, e);
Resize(this, e);
}
#endregion
@ -819,7 +887,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnTitleChanged(EventArgs e)
{
if (TitleChanged != null) TitleChanged(this, e);
TitleChanged(this, e);
}
#endregion
@ -832,7 +900,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnVisibleChanged(EventArgs e)
{
if (VisibleChanged != null) VisibleChanged(this, e);
VisibleChanged(this, e);
}
#endregion
@ -845,7 +913,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnWindowBorderChanged(EventArgs e)
{
if (WindowBorderChanged != null) WindowBorderChanged(this, e);
WindowBorderChanged(this, e);
}
#endregion
@ -858,7 +926,7 @@ namespace OpenTK
/// <param name="e">Not used.</param>
protected virtual void OnWindowStateChanged(EventArgs e)
{
if (WindowStateChanged != null) WindowStateChanged(this, e);
WindowStateChanged(this, e);
}
#endregion

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@ -57,6 +57,7 @@
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DebugType>full</DebugType>
<GenerateDocumentation>true</GenerateDocumentation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -76,6 +77,11 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Documentation|AnyCPU'">
<OutputPath>..\..\Binaries\OpenTK\Release\</OutputPath>
<DebugType>none</DebugType>
<WarningLevel>4</WarningLevel>
<Optimize>true</Optimize>
<DefineConstants>TRACE;</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Nsis|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -112,10 +118,6 @@
<Name>System.Drawing</Name>
<Private>False</Private>
</Reference>
<Reference Include="System.Windows.Forms">
<Name>System.Windows.Forms</Name>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Name>System.Xml</Name>
<Private>False</Private>
@ -128,6 +130,14 @@
<Compile Include="DisplayDevice.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="DisplayIndex.cs" />
<Compile Include="Graphics\GraphicsModeComparer.cs" />
<Compile Include="Input\IGamePadDriver.cs" />
<Compile Include="Input\IInputDriver2.cs" />
<Compile Include="Input\IKeyboardDriver2.cs" />
<Compile Include="Input\IMouseDriver2.cs" />
<Compile Include="Platform\DisplayDeviceBase.cs" />
<Compile Include="Platform\Windows\WinInputBase.cs" />
<Compile Include="WindowBorder.cs">
<SubType>Code</SubType>
</Compile>
@ -548,9 +558,6 @@
<Compile Include="Input\MouseState.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Input\InputDriver.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Input\GamePadState.cs">
<SubType>Code</SubType>
</Compile>
@ -753,9 +760,15 @@
<None Include="..\..\OpenTK.snk">
<Link>OpenTK.snk</Link>
</None>
<None Include="OpenTK.dll.config">
<Compile Include="Platform\X11\X11Keyboard.cs" />
<Compile Include="Platform\X11\X11Mouse.cs" />
<Compile Include="Input\ButtonState.cs" />
<Compile Include="Platform\X11\XI2Mouse.cs" />
<EmbeddedResource Include="OpenTK.dll.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</EmbeddedResource>
<Compile Include="Platform\MacOS\HIDInput.cs" />
<Compile Include="IntPtrEqualityComparer.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View file

@ -0,0 +1,53 @@
#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.Text;
namespace OpenTK.Platform
{
abstract class DisplayDeviceBase : IDisplayDeviceDriver
{
protected readonly List<DisplayDevice> AvailableDevices = new List<DisplayDevice>();
protected DisplayDevice Primary;
public abstract bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution);
public abstract bool TryRestoreResolution(DisplayDevice device);
// Gets the DisplayDevice that corresponds to the specified index.
public virtual DisplayDevice GetDisplay(DisplayIndex index)
{
if (index == DisplayIndex.Primary)
return Primary;
else if ((int)index >= 0 && (int)index < AvailableDevices.Count)
return AvailableDevices[(int)index];
else
return null;
}
}
}

View file

@ -114,11 +114,16 @@ namespace OpenTK.Platform
return default_implementation.CreateGraphicsMode();
}
public OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
return default_implementation.CreateKeyboardDriver();
}
public OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
return default_implementation.CreateMouseDriver();
}
class UnsupportedPlatform : IPlatformFactory
{
#region Fields
@ -164,7 +169,12 @@ namespace OpenTK.Platform
throw new PlatformNotSupportedException(error_string);
}
public OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
throw new PlatformNotSupportedException(error_string);
}
public OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
throw new PlatformNotSupportedException(error_string);
}

View file

@ -1,9 +1,28 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK team.
* This notice may not be removed.
* See license.txt for licensing detailed licensing details.
*/
#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;
@ -16,5 +35,6 @@ namespace OpenTK.Platform
{
bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution);
bool TryRestoreResolution(DisplayDevice device);
DisplayDevice GetDisplay(DisplayIndex displayIndex);
}
}

View file

@ -47,6 +47,8 @@ namespace OpenTK.Platform
IGraphicsMode CreateGraphicsMode();
OpenTK.Input.IKeyboardDriver CreateKeyboardDriver();
OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver();
OpenTK.Input.IMouseDriver2 CreateMouseDriver();
}
}

View file

@ -1,17 +1,36 @@
#region License
//
//
// AglContext.cs
// The Open Toolkit Library License
//
// Created by Erik Ylvisaker on 3/17/08.
// Copyright 2008. All rights reserved.
// 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
// Created by Erik Ylvisaker on 3/17/08.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Control = System.Windows.Forms.Control;
namespace OpenTK.Platform.MacOS
{
@ -23,41 +42,40 @@ namespace OpenTK.Platform.MacOS
using AGLContext = IntPtr;
using AGLPbuffer = IntPtr;
class AglContext : DesktopGraphicsContext
class AglContext : DesktopGraphicsContext
{
bool mVSync = false;
// Todo: keep track of which display adapter was specified when the context was created.
// IntPtr displayID;
GraphicsMode graphics_mode;
CarbonWindowInfo carbonWindow;
IntPtr shareContextRef;
DisplayDevice device;
bool mIsFullscreen = false;
DisplayDevice device;
bool mIsFullscreen = false;
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
{
Debug.Print("Context Type: {0}", shareContext);
Debug.Print("Window info: {0}", window);
this.graphics_mode = mode;
this.carbonWindow = (CarbonWindowInfo)window;
if (shareContext is AglContext)
shareContextRef = ((AglContext)shareContext).Handle.Handle;
if (shareContext is GraphicsContext)
{
ContextHandle shareHandle = shareContext != null ?
(shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
shareContextRef = shareHandle.Handle;
}
if (shareContextRef == IntPtr.Zero)
{
Debug.Print("No context sharing will take place.");
}
if (shareContext is GraphicsContext)
{
ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
shareContextRef = shareHandle.Handle;
}
if (shareContextRef == IntPtr.Zero)
{
Debug.Print("No context sharing will take place.");
}
CreateContext(mode, carbonWindow, shareContextRef, true);
}
@ -67,7 +85,7 @@ namespace OpenTK.Platform.MacOS
throw new ArgumentException("handle");
if (window == null)
throw new ArgumentNullException("window");
Handle = handle;
carbonWindow = (CarbonWindowInfo)window;
}
@ -76,37 +94,36 @@ namespace OpenTK.Platform.MacOS
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
{
Debug.Print(pixelFormatAttribute.ToString());
aglAttributes.Add((int)pixelFormatAttribute);
}
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value)
{
Debug.Print("{0} : {1}", pixelFormatAttribute, value);
aglAttributes.Add((int)pixelFormatAttribute);
aglAttributes.Add(value);
}
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow,
IntPtr shareContextRef, bool fullscreen)
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen)
{
List<int> aglAttributes = new List<int>();
List<int> aglAttributes = new List<int>();
Debug.Print("AGL pixel format attributes:");
Debug.Indent();
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RED_SIZE, mode.ColorFormat.Red);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_GREEN_SIZE, mode.ColorFormat.Green);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
if (mode.Depth > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
if (mode.Stencil > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
if (mode.AccumulatorFormat.BitsPerPixel > 0)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
@ -120,72 +137,68 @@ namespace OpenTK.Platform.MacOS
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB, 1);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, mode.Samples);
}
if (fullscreen)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
Debug.Unindent();
Debug.Write("Attribute array: ");
for (int i = 0; i < aglAttributes.Count; i++)
Debug.Write(aglAttributes[i].ToString() + " ");
Debug.WriteLine("");
AGLPixelFormat myAGLPixelFormat;
// Choose a pixel format with the attributes we specified.
if (fullscreen)
{
IntPtr gdevice;
IntPtr cgdevice = GetQuartzDevice(carbonWindow);
if (cgdevice == IntPtr.Zero)
cgdevice = QuartzDisplayDeviceDriver.MainDisplay;
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(
cgdevice, out gdevice, false);
IntPtr gdevice;
IntPtr cgdevice = GetQuartzDevice(carbonWindow);
if (cgdevice == IntPtr.Zero)
cgdevice = (IntPtr)DisplayDevice.Default.Id;
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(cgdevice, out gdevice, false);
if (status != OSStatus.NoError)
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
myAGLPixelFormat = Agl.aglChoosePixelFormat(
ref gdevice, 1,
aglAttributes.ToArray());
myAGLPixelFormat = Agl.aglChoosePixelFormat(ref gdevice, 1, aglAttributes.ToArray());
Agl.AglError err = Agl.GetError();
if (err == Agl.AglError.BadPixelFormat)
{
Debug.Print("Failed to create full screen pixel format.");
Debug.Print("Trying again to create a non-fullscreen pixel format.");
CreateContext(mode, carbonWindow, shareContextRef, false);
return;
}
}
else
{
myAGLPixelFormat = Agl.aglChoosePixelFormat(
IntPtr.Zero, 0,
aglAttributes.ToArray());
myAGLPixelFormat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, aglAttributes.ToArray());
MyAGLReportError("aglChoosePixelFormat");
}
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
// create the context and share it with the share reference.
Handle = new ContextHandle( Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
MyAGLReportError("aglCreateContext");
// Free the pixel format from memory.
Agl.aglDestroyPixelFormat(myAGLPixelFormat);
MyAGLReportError("aglDestroyPixelFormat");
Debug.Print("IsControl: {0}", carbonWindow.IsControl);
SetDrawable(carbonWindow);
@ -193,46 +206,48 @@ namespace OpenTK.Platform.MacOS
Update(carbonWindow);
MakeCurrent(carbonWindow);
Debug.Print("context: {0}", Handle.Handle);
}
private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow)
{
IntPtr windowRef = carbonWindow.WindowRef;
if (CarbonGLNative.WindowRefMap.ContainsKey(windowRef) == false)
return IntPtr.Zero;
WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
if (nativeRef.IsAlive == false)
return IntPtr.Zero;
CarbonGLNative window = nativeRef.Target as CarbonGLNative;
if (window == null)
return IntPtr.Zero;
return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
}
private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow)
{
IntPtr windowRef = carbonWindow.WindowRef;
if (CarbonGLNative.WindowRefMap.ContainsKey(windowRef) == false)
return IntPtr.Zero;
WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
if (nativeRef.IsAlive == false)
return IntPtr.Zero;
CarbonGLNative window = nativeRef.Target as CarbonGLNative;
if (window == null)
return IntPtr.Zero;
return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
}
void SetBufferRect(CarbonWindowInfo carbonWindow)
{
if (carbonWindow.IsControl == false)
return;
// Todo: See if there is a way around using WinForms.
throw new NotImplementedException();
#if false
System.Windows.Forms.Control ctrl = Control.FromHandle(carbonWindow.WindowRef);
if (ctrl.TopLevelControl == null)
return;
Rect rect = API.GetControlBounds(carbonWindow.WindowRef);
System.Windows.Forms.Form frm = (System.Windows.Forms.Form) ctrl.TopLevelControl;
System.Drawing.Point loc =
frm.PointToClient(ctrl.PointToScreen(System.Drawing.Point.Empty));
System.Windows.Forms.Form frm = (System.Windows.Forms.Form)ctrl.TopLevelControl;
System.Drawing.Point loc = frm.PointToClient(ctrl.PointToScreen(System.Drawing.Point.Empty));
rect.X = (short)loc.X;
rect.Y = (short)loc.Y;
@ -243,28 +258,28 @@ namespace OpenTK.Platform.MacOS
Debug.Print(" AGL Coordinate Rect: {0}", rect);
int[] glrect = new int[4];
glrect[0] = rect.X;
glrect[1] = rect.Y;
glrect[2] = rect.Width;
glrect[3] = rect.Height;
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
MyAGLReportError("aglSetInteger");
Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT);
MyAGLReportError("aglEnable");
#endif
}
void SetDrawable(CarbonWindowInfo carbonWindow)
{
IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow);
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
Agl.aglSetDrawable(Handle.Handle, windowPort);
MyAGLReportError("aglSetDrawable");
}
private static IntPtr GetWindowPortForWindowInfo(CarbonWindowInfo carbonWindow)
@ -276,109 +291,109 @@ namespace OpenTK.Platform.MacOS
windowPort = API.GetWindowPort(controlOwner);
}
else
windowPort = API.GetWindowPort(carbonWindow.WindowRef);
return windowPort;
}
public override void Update(IWindowInfo window)
public override void Update(IWindowInfo window)
{
CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window;
if (carbonWindow.GoFullScreenHack)
{
carbonWindow.GoFullScreenHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.SetFullscreen(this);
else
Debug.Print("Could not find window!");
return;
}
if (carbonWindow.GoFullScreenHack)
{
carbonWindow.GoFullScreenHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.SetFullscreen(this);
else
Debug.Print("Could not find window!");
return;
}
else if (carbonWindow.GoWindowedHack)
{
carbonWindow.GoWindowedHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.UnsetFullscreen(this);
else
Debug.Print("Could not find window!");
}
if (mIsFullscreen)
return;
else if (carbonWindow.GoWindowedHack)
{
carbonWindow.GoWindowedHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.UnsetFullscreen(this);
else
Debug.Print("Could not find window!");
}
if (mIsFullscreen)
return;
SetDrawable(carbonWindow);
SetBufferRect(carbonWindow);
Agl.aglUpdateContext(Handle.Handle);
}
private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
{
WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.WindowRef];
private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
{
WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.WindowRef];
if (r.IsAlive)
{
return (CarbonGLNative)r.Target;
}
if (r.IsAlive)
{
return (CarbonGLNative) r.Target;
}
else
return null;
}
else
return null;
}
void MyAGLReportError(string function)
{
Agl.AglError err = Agl.GetError();
if (err != Agl.AglError.NoError)
throw new MacOSException((OSStatus)err, string.Format(
"AGL Error from function {0}: {1} {2}",
function, err, Agl.ErrorString(err)));
throw new MacOSException((OSStatus)err, string.Format("AGL Error from function {0}: {1} {2}", function, err, Agl.ErrorString(err)));
}
bool firstFullScreen = false;
internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height)
{
CarbonGLNative wind = GetCarbonWindow(info);
Debug.Print("Switching to full screen {0}x{1} on context {2}",
wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, Handle.Handle);
CG.DisplayCapture(GetQuartzDevice(info));
Agl.aglSetFullScreen(Handle.Handle, wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, 0, 0);
MakeCurrent(info);
width = wind.TargetDisplayDevice.Width;
height = wind.TargetDisplayDevice.Height;
CarbonGLNative wind = GetCarbonWindow(info);
Debug.Print("Switching to full screen {0}x{1} on context {2}", wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, Handle.Handle);
CG.DisplayCapture(GetQuartzDevice(info));
Agl.aglSetFullScreen(Handle.Handle, wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, 0, 0);
MakeCurrent(info);
width = wind.TargetDisplayDevice.Width;
height = wind.TargetDisplayDevice.Height;
// This is a weird hack to workaround a bug where the first time a context
// is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen
// and redo it as fullscreen.
if (firstFullScreen == false)
{
firstFullScreen = true;
UnsetFullScreen(info);
SetFullScreen(info, out width, out height);
}
mIsFullscreen = true;
if (firstFullScreen == false)
{
firstFullScreen = true;
UnsetFullScreen(info);
SetFullScreen(info, out width, out height);
}
mIsFullscreen = true;
}
internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
{
Debug.Print("Unsetting AGL fullscreen.");
Debug.Print("Unsetting AGL fullscreen.");
Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
Agl.aglUpdateContext(Handle.Handle);
CG.DisplayRelease(GetQuartzDevice(windowInfo));
Debug.Print("Resetting drawable.");
SetDrawable(windowInfo);
mIsFullscreen = false;
Agl.aglUpdateContext(Handle.Handle);
CG.DisplayRelease(GetQuartzDevice(windowInfo));
Debug.Print("Resetting drawable.");
SetDrawable(windowInfo);
mIsFullscreen = false;
}
@ -393,14 +408,14 @@ namespace OpenTK.Platform.MacOS
{
Debug.WriteLine("--> Resetting drawable. <--");
firstSwap = true;
SetDrawable(carbonWindow);
Update(carbonWindow);
SetDrawable(carbonWindow);
Update(carbonWindow);
}
Agl.aglSwapBuffers(Handle.Handle);
MyAGLReportError("aglSwapBuffers");
Agl.aglSwapBuffers(Handle.Handle);
MyAGLReportError("aglSwapBuffers");
}
public override void MakeCurrent(IWindowInfo window)
{
if (Agl.aglSetCurrentContext(Handle.Handle) == false)
@ -409,24 +424,18 @@ namespace OpenTK.Platform.MacOS
public override bool IsCurrent
{
get
{
return (Handle.Handle == Agl.aglGetCurrentContext());
}
get { return (Handle.Handle == Agl.aglGetCurrentContext()); }
}
public override bool VSync
{
get
{
return mVSync;
}
get { return mVSync; }
set
{
int intVal = value ? 1 : 0;
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_SWAP_INTERVAL, ref intVal);
mVSync = value;
}
}
@ -449,34 +458,34 @@ namespace OpenTK.Platform.MacOS
{
if (IsDisposed || Handle.Handle == IntPtr.Zero)
return;
Debug.Print("Disposing of AGL context.");
Agl.aglSetCurrentContext(IntPtr.Zero);
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
// I do not know MacOS allows us to destroy a context from a separate thread,
// like the finalizer thread. It's untested, but worst case is probably
// an exception on application exit, which would be logged to the console.
Debug.Print("Destroying context");
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
// I do not know MacOS allows us to destroy a context from a separate thread,
// like the finalizer thread. It's untested, but worst case is probably
// an exception on application exit, which would be logged to the console.
Debug.Print("Destroying context");
if (Agl.aglDestroyContext(Handle.Handle) == true)
{
Debug.Print("Context destruction completed successfully.");
Handle = ContextHandle.Zero;
return;
Debug.Print("Context destruction completed successfully.");
Handle = ContextHandle.Zero;
return;
}
// failed to destroy context.
Debug.WriteLine("Failed to destroy context.");
Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
// don't throw an exception from the finalizer thread.
if (disposing)
{
throw new MacOSException((OSStatus)Agl.GetError(), Agl.ErrorString(Agl.GetError()));
}
IsDisposed = true;
}
@ -484,7 +493,7 @@ namespace OpenTK.Platform.MacOS
#region IGraphicsContextInternal Members
private const string Library = "libdl.dylib";
private const string Library = "libdl.dylib";
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
private static extern bool NSIsSymbolNameDefined(string s);
@ -498,14 +507,14 @@ namespace OpenTK.Platform.MacOS
string fname = "_" + function;
if (!NSIsSymbolNameDefined(fname))
return IntPtr.Zero;
IntPtr symbol = NSLookupAndBindSymbol(fname);
if (symbol != IntPtr.Zero)
symbol = NSAddressOfSymbol(symbol);
return symbol;
}
#endregion
}
}

View file

@ -1,11 +1,31 @@
#region License
//
//
// xCSCarbon
// The Open Toolkit Library License
//
// Created by Erik Ylvisaker on 3/17/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
// 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
// Created by Erik Ylvisaker on 3/17/08.
using System;
using System.Collections.Generic;
@ -27,35 +47,36 @@ namespace OpenTK.Platform.MacOS.Carbon
Initialize();
}
internal static void Initialize()
static internal void Initialize()
{
if (mInitialized) return;
if (mInitialized)
return;
API.AcquireRootMenu();
ConnectEvents();
API.Gestalt(GestaltSelector.SystemVersionMajor, out osMajor);
API.Gestalt(GestaltSelector.SystemVersionMinor, out osMinor);
API.Gestalt(GestaltSelector.SystemVersionBugFix, out osBugfix);
Debug.Print("Running on Mac OS X {0}.{1}.{2}.", osMajor, osMinor, osBugfix);
TransformProcessToForeground();
TransformProcessToForeground();
}
private static void TransformProcessToForeground()
{
Carbon.ProcessSerialNumber psn = new ProcessSerialNumber();
private static void TransformProcessToForeground()
{
Carbon.ProcessSerialNumber psn = new ProcessSerialNumber();
Debug.Print("Setting process to be foreground application.");
API.GetCurrentProcess(ref psn);
API.TransformProcessType(ref psn, ProcessApplicationTransformState.kProcessTransformToForegroundApplication);
API.SetFrontProcess(ref psn);
}
Debug.Print("Setting process to be foreground application.");
API.GetCurrentProcess(ref psn);
API.TransformProcessType(ref psn, ProcessApplicationTransformState.kProcessTransformToForegroundApplication);
API.SetFrontProcess(ref psn);
}
internal static CarbonGLNative WindowEventHandler
static internal CarbonGLNative WindowEventHandler
{
get { return eventHandler; }
set { eventHandler = value; }
@ -63,33 +84,16 @@ namespace OpenTK.Platform.MacOS.Carbon
static void ConnectEvents()
{
EventTypeSpec[] eventTypes = new EventTypeSpec[]
{
new EventTypeSpec(EventClass.Application, AppEventKind.AppActivated),
new EventTypeSpec(EventClass.Application, AppEventKind.AppDeactivated),
new EventTypeSpec(EventClass.Application, AppEventKind.AppQuit),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDown),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseUp),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseMoved),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDragged),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseEntered),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseExited),
new EventTypeSpec(EventClass.Mouse, MouseEventKind.WheelMoved),
new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyDown),
new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyRepeat),
new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyUp),
new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged),
new EventTypeSpec(EventClass.AppleEvent, AppleEventKind.AppleEvent),
};
EventTypeSpec[] eventTypes = new EventTypeSpec[] { new EventTypeSpec(EventClass.Application, AppEventKind.AppActivated), new EventTypeSpec(EventClass.Application, AppEventKind.AppDeactivated), new EventTypeSpec(EventClass.Application, AppEventKind.AppQuit), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDown), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseUp), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseMoved), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseDragged), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseEntered), new EventTypeSpec(EventClass.Mouse, MouseEventKind.MouseExited), new EventTypeSpec(EventClass.Mouse, MouseEventKind.WheelMoved),
new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyDown), new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyRepeat), new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyUp), new EventTypeSpec(EventClass.Keyboard, KeyboardEventKind.RawKeyModifiersChanged), new EventTypeSpec(EventClass.AppleEvent, AppleEventKind.AppleEvent) };
MacOSEventHandler handler = EventHandler;
uppHandler = API.NewEventHandlerUPP(handler);
API.InstallApplicationEventHandler(
uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
API.InstallApplicationEventHandler(uppHandler, eventTypes, IntPtr.Zero, IntPtr.Zero);
mInitialized = true;
}
@ -100,28 +104,30 @@ namespace OpenTK.Platform.MacOS.Carbon
switch (evt.EventClass)
{
case EventClass.Application:
switch (evt.AppEventKind)
{
default:
return OSStatus.EventNotHandled;
}
case EventClass.Application:
switch (evt.AppEventKind)
{
default:
return OSStatus.EventNotHandled;
}
case EventClass.AppleEvent:
// only event here is the apple event.
Debug.Print("Processing apple event.");
API.ProcessAppleEvent(inEvent);
break;
case EventClass.AppleEvent:
// only event here is the apple event.
Debug.Print("Processing apple event.");
API.ProcessAppleEvent(inEvent);
break;
case EventClass.Keyboard:
case EventClass.Mouse:
if (WindowEventHandler != null)
{
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
}
case EventClass.Keyboard:
case EventClass.Mouse:
if (WindowEventHandler != null)
{
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
}
break;
break;
}
return OSStatus.EventNotHandled;
}
@ -129,9 +135,9 @@ namespace OpenTK.Platform.MacOS.Carbon
{
window.Closed += MainWindowClosed;
window.Visible = true;
API.RunApplicationEventLoop();
window.Closed -= MainWindowClosed;
}
@ -142,7 +148,7 @@ namespace OpenTK.Platform.MacOS.Carbon
}
internal static void ProcessEvents()
static internal void ProcessEvents()
{
API.ProcessEvents();
}

View file

@ -1,11 +1,32 @@
#region License
//
//
// Agl.cs
// 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
// Created by Erik Ylvisaker on 3/17/08.
// Copyright 2008. All rights reserved.
//
//
using System;
using System.Diagnostics;
@ -297,7 +318,7 @@ namespace OpenTK.Platform.MacOS
[DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(IntPtr gdevs, int ndev, int []attribs);
[DllImport(agl)] internal static extern void aglDestroyPixelFormat(AGLPixelFormat pix);
[DllImport(agl)] internal static extern AGLPixelFormat aglNextPixelFormat(AGLPixelFormat pix);
[DllImport(agl)] static extern byte aglDescribePixelFormat(AGLPixelFormat pix, int attrib, out int value);
[DllImport(agl)] internal static extern bool aglDescribePixelFormat(AGLPixelFormat pix, PixelFormatAttribute attrib, out int value);
[Obsolete("Use aglDisplaysOfPixelFormat instead.")]
[DllImport(agl)] static extern AGLDevice *aglDevicesOfPixelFormat(AGLPixelFormat pix, int *ndevs);

View file

@ -1,11 +1,32 @@
#region License
//
//
// Carbon.cs
// 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
// Created by Erik Ylvisaker on 3/17/08.
// Copyright 2008. All rights reserved.
//
//
using System;
using System.Runtime.InteropServices;
@ -99,6 +120,14 @@ namespace OpenTK.Platform.MacOS.Carbon
{
public float X;
public float Y;
public HIPoint(float x, float y)
{
X = x;
Y = y;
}
public HIPoint(double x, double y)
: this((float)x, (float)y)
{ }
}
[StructLayout(LayoutKind.Sequential)]
internal struct HISize
@ -706,17 +735,31 @@ namespace OpenTK.Platform.MacOS.Carbon
unsafe
{
HIPoint* parm = &point;
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.WindowMouseLocation, EventParamType.typeHIPoint, IntPtr.Zero,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero,
(IntPtr)parm);
pt = point;
return result;
}
}
static internal OSStatus GetEventMouseDelta(IntPtr inEvent, out HIPoint pt)
{
HIPoint point;
unsafe
{
HIPoint* parm = &point;
OSStatus result = API.GetEventParameter(inEvent,
EventParamName.MouseDelta, EventParamType.typeHIPoint, IntPtr.Zero,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(HIPoint)), IntPtr.Zero,
(IntPtr)parm);
pt = point;
return result;
}
}
static internal OSStatus GetEventWindowRef(IntPtr inEvent, out IntPtr windowRef)

View file

@ -1,3 +1,30 @@
#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.Runtime.InteropServices;
@ -5,6 +32,8 @@ using System.Text;
namespace OpenTK.Platform.MacOS.Carbon
{
using CFRunLoop = System.IntPtr;
struct CFArray
{
IntPtr arrayRef;
@ -112,5 +141,25 @@ namespace OpenTK.Platform.MacOS.Carbon
kCFNumberCGFloatType = 16,
kCFNumberMaxType = 16
};
public enum CFRunLoopExitReason
{
Finished = 1,
Stopped = 2,
TimedOut = 3,
HandledSource = 4
}
public static readonly IntPtr RunLoopModeDefault = CF.CFSTR("kCFRunLoopDefaultMode");
[DllImport(appServices)]
internal static extern CFRunLoop CFRunLoopGetCurrent();
[DllImport(appServices)]
internal static extern CFRunLoop CFRunLoopGetMain();
[DllImport(appServices)]
internal static extern CFRunLoopExitReason CFRunLoopRunInMode(
IntPtr cfstrMode, double interval, bool returnAfterSourceHandled);
}
}

View file

@ -1,3 +1,30 @@
#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.Text;

View file

@ -1,10 +1,38 @@
#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.Runtime.InteropServices;
using System.Diagnostics;
namespace OpenTK.Platform.MacOS.Carbon
{
using CGDirectDisplayID = System.IntPtr;
// Quartz Display services used here are available in MacOS X 10.3 and later.
enum CGDisplayErr
@ -12,6 +40,21 @@ namespace OpenTK.Platform.MacOS.Carbon
}
enum CGError
{
Success = 0,
Failure = 1000,
IllegalArgument = 1001,
InvalidConnection = 1002,
InvalidContext = 1003,
CannotComplete = 1004,
NotImplemented = 1006,
RangeCheck = 1007,
TypeCheck = 1008,
InvalidOperation = 1010,
NoneAvailable = 1011,
}
internal static class CG
{
const string appServices = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices";
@ -50,5 +93,22 @@ namespace OpenTK.Platform.MacOS.Carbon
[DllImport(appServices, EntryPoint = "CGDisplaySwitchToMode")]
internal static extern IntPtr DisplaySwitchToMode(IntPtr display, IntPtr displayMode);
[DllImport(appServices, EntryPoint = "CGWarpMouseCursorPosition")]
internal static extern CGError WarpMouseCursorPosition(HIPoint newCursorPosition);
[DllImport(appServices, EntryPoint = "CGCursorIsVisible")]
internal static extern bool CursorIsVisible();
[DllImport(appServices, EntryPoint = "CGDisplayShowCursor")]
internal static extern CGError DisplayShowCursor(CGDirectDisplayID display);
[DllImport(appServices, EntryPoint = "CGDisplayHideCursor")]
internal static extern CGError DisplayHideCursor(CGDirectDisplayID display);
[DllImport(appServices, EntryPoint = "CGAssociateMouseAndMouseCursorPosition")]
internal static extern CGError AssociateMouseAndMouseCursorPosition(bool connected);
[DllImport(appServices, EntryPoint="CGSetLocalEventsSuppressionInterval")]
internal static extern CGError SetLocalEventsSuppressionInterval(double seconds);
}
}

View file

@ -1,3 +1,30 @@
#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;

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,30 @@
#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;
@ -7,7 +34,7 @@ namespace OpenTK.Platform.MacOS
{
using Input;
class CarbonInput : IInputDriver
class CarbonInput : IInputDriver, IInputDriver2
{
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(1);
@ -62,5 +89,29 @@ namespace OpenTK.Platform.MacOS
}
#endregion
public IMouseDriver2 MouseDriver
{
get
{
throw new NotImplementedException();
}
}
public IKeyboardDriver2 KeyboardDriver
{
get
{
throw new NotImplementedException();
}
}
public IGamePadDriver GamePadDriver
{
get
{
throw new NotImplementedException();
}
}
}
}

View file

@ -36,14 +36,14 @@ namespace OpenTK.Platform.MacOS
/// <summary>
/// Describes a Carbon window.
/// </summary>
sealed class CarbonWindowInfo : IWindowInfo
sealed class CarbonWindowInfo : IWindowInfo
{
IntPtr windowRef;
bool ownHandle = false;
bool disposed = false;
bool isControl = false;
bool goFullScreenHack = false;
bool goWindowedHack = false;
bool goFullScreenHack = false;
bool goWindowedHack = false;
#region Constructors
@ -72,16 +72,16 @@ namespace OpenTK.Platform.MacOS
get { return this.windowRef; }
}
internal bool GoFullScreenHack
{
get { return goFullScreenHack; }
set { goFullScreenHack = value; }
}
internal bool GoWindowedHack
{
get { return goWindowedHack; }
set { goWindowedHack = value; }
}
internal bool GoFullScreenHack
{
get { return goFullScreenHack; }
set { goFullScreenHack = value; }
}
internal bool GoWindowedHack
{
get { return goWindowedHack; }
set { goWindowedHack = value; }
}
/// <summary>
@ -96,8 +96,7 @@ namespace OpenTK.Platform.MacOS
/// <returns>A System.String that represents the current window.</returns>
public override string ToString()
{
return String.Format("MacOS.CarbonWindowInfo: Handle {0}",
this.WindowRef);
return String.Format("MacOS.CarbonWindowInfo: Handle {0}", this.WindowRef);
}
#endregion
@ -113,19 +112,19 @@ namespace OpenTK.Platform.MacOS
{
if (disposed)
return;
if (disposing)
{
}
if (ownHandle)
{
Debug.Print("Disposing window {0}.", windowRef);
Carbon.API.DisposeWindow(this.windowRef);
windowRef = IntPtr.Zero;
}
disposed = true;
}
@ -133,7 +132,7 @@ namespace OpenTK.Platform.MacOS
{
Dispose(false);
}
#endregion
}
}

View file

@ -1,11 +1,31 @@
#region License
//
//
// xCSCarbon
// 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
// Created by Erik Ylvisaker on 3/17/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
//
using System;
using System.Collections.Generic;
@ -25,14 +45,17 @@ namespace OpenTK.Platform.MacOS.Carbon
uint _eventKind;
EventClass _eventClass;
public EventClass EventClass { get { return _eventClass; }}
public EventClass EventClass
{
get { return _eventClass; }
}
public WindowEventKind WindowEventKind
{
get
{
if (EventClass == EventClass.Window)
return (WindowEventKind) _eventKind;
return (WindowEventKind)_eventKind;
else
throw new InvalidCastException("Event is not a Window event.");
}
@ -42,7 +65,7 @@ namespace OpenTK.Platform.MacOS.Carbon
get
{
if (EventClass == EventClass.Keyboard)
return (KeyboardEventKind) _eventKind;
return (KeyboardEventKind)_eventKind;
else
throw new InvalidCastException("Event is not a Keyboard event.");
}
@ -52,7 +75,7 @@ namespace OpenTK.Platform.MacOS.Carbon
get
{
if (EventClass == EventClass.Mouse)
return (MouseEventKind) _eventKind;
return (MouseEventKind)_eventKind;
else
throw new InvalidCastException("Event is not an Mouse event.");
}
@ -62,7 +85,7 @@ namespace OpenTK.Platform.MacOS.Carbon
get
{
if (EventClass == EventClass.Application)
return (AppEventKind) _eventKind;
return (AppEventKind)_eventKind;
else
throw new InvalidCastException("Event is not an Application event.");
}
@ -71,18 +94,18 @@ namespace OpenTK.Platform.MacOS.Carbon
public override string ToString()
{
switch(EventClass)
switch (EventClass)
{
case EventClass.Application:
return "Event: App " + AppEventKind.ToString();
case EventClass.Keyboard:
return "Event: Keyboard " + KeyboardEventKind.ToString();
case EventClass.Mouse:
return "Event: Mouse " + MouseEventKind.ToString();
case EventClass.Window:
return "Event: Window " + WindowEventKind.ToString();
case EventClass.Application:
return "Event: App " + AppEventKind.ToString();
case EventClass.Keyboard:
return "Event: Keyboard " + KeyboardEventKind.ToString();
case EventClass.Mouse:
return "Event: Mouse " + MouseEventKind.ToString();
case EventClass.Window:
return "Event: Window " + WindowEventKind.ToString();
}
return "Event: Unknown Class " + EventClass.ToString() + " kind: " + _eventKind.ToString();
}
}

View file

@ -0,0 +1,937 @@
#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;
using System.Runtime.InteropServices;
using OpenTK.Input;
namespace OpenTK.Platform.MacOS
{
using Carbon;
using CFAllocatorRef = System.IntPtr;
using CFDictionaryRef = System.IntPtr;
using CFIndex = System.IntPtr;
using CFRunLoop = System.IntPtr;
using CFString = System.IntPtr;
using CFStringRef = System.IntPtr; // Here used interchangeably with the CFString
using CFTypeRef = System.IntPtr;
using IOHIDDeviceRef = System.IntPtr;
using IOHIDElementRef = System.IntPtr;
using IOHIDManagerRef = System.IntPtr;
using IOHIDValueRef = System.IntPtr;
using IOOptionBits = System.IntPtr;
using IOReturn = System.IntPtr;
// Requires Mac OS X 10.5 or higher.
// Todo: create a driver for older installations. Maybe use CGGetLastMouseDelta for that?
class HIDInput : IInputDriver2, IMouseDriver2, IKeyboardDriver2
{
#region Fields
readonly IOHIDManagerRef hidmanager;
readonly Dictionary<IntPtr, MouseState> MouseDevices =
new Dictionary<IntPtr, MouseState>(new IntPtrEqualityComparer());
readonly Dictionary<int, IntPtr> MouseIndexToDevice =
new Dictionary<int, IntPtr>();
readonly Dictionary<IntPtr, KeyboardState> KeyboardDevices =
new Dictionary<IntPtr, KeyboardState>(new IntPtrEqualityComparer());
readonly Dictionary<int, IntPtr> KeyboardIndexToDevice =
new Dictionary<int, IntPtr>();
readonly CFRunLoop RunLoop = CF.CFRunLoopGetMain();
readonly CFString InputLoopMode = CF.RunLoopModeDefault;
readonly CFDictionary DeviceTypes = new CFDictionary();
readonly NativeMethods.IOHIDDeviceCallback HandleDeviceAdded;
readonly NativeMethods.IOHIDDeviceCallback HandleDeviceRemoved;
readonly NativeMethods.IOHIDValueCallback HandleDeviceValueReceived;
#endregion
#region Constructors
public HIDInput()
{
Debug.Print("Using HIDInput.");
HandleDeviceAdded = DeviceAdded;
HandleDeviceRemoved = DeviceRemoved;
HandleDeviceValueReceived = DeviceValueReceived;
hidmanager = CreateHIDManager();
RegisterHIDCallbacks(hidmanager);
}
#endregion
#region Private Members
IOHIDManagerRef CreateHIDManager()
{
return NativeMethods.IOHIDManagerCreate(IntPtr.Zero, IntPtr.Zero);
}
// Registers callbacks for device addition and removal. These callbacks
// are called when we run the loop in CheckDevicesMode
void RegisterHIDCallbacks(IOHIDManagerRef hidmanager)
{
NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(
hidmanager, HandleDeviceAdded, IntPtr.Zero);
NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(
hidmanager, HandleDeviceRemoved, IntPtr.Zero);
NativeMethods.IOHIDManagerScheduleWithRunLoop(hidmanager,
RunLoop, InputLoopMode);
NativeMethods.IOHIDManagerSetDeviceMatching(hidmanager, DeviceTypes.Ref);
NativeMethods.IOHIDManagerOpen(hidmanager, IOOptionBits.Zero);
OpenTK.Platform.MacOS.Carbon.CF.CFRunLoopRunInMode(InputLoopMode, 0.0, true);
}
void DeviceAdded(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
{
if (NativeMethods.IOHIDDeviceOpen(device, IOOptionBits.Zero) == IOReturn.Zero)
{
if (NativeMethods.IOHIDDeviceConformsTo(device,
HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse))
{
if (!MouseDevices.ContainsKey(device))
{
Debug.Print("Mouse device {0} discovered", device);
MouseState state = new MouseState();
state.IsConnected = true;
MouseIndexToDevice.Add(MouseDevices.Count, device);
MouseDevices.Add(device, state);
}
else
{
Debug.Print("Mouse device {0} reconnected", device);
MouseState state = MouseDevices[device];
state.IsConnected = true;
MouseDevices[device] = state;
}
}
if (NativeMethods.IOHIDDeviceConformsTo(device,
HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard))
{
if (!KeyboardDevices.ContainsKey(device))
{
Debug.Print("Keyboard device {0} discovered", device);
KeyboardState state = new KeyboardState();
state.IsConnected = true;
KeyboardIndexToDevice.Add(KeyboardDevices.Count, device);
KeyboardDevices.Add(device, state);
}
else
{
Debug.Print("Keyboard device {0} reconnected", device);
KeyboardState state = KeyboardDevices[device];
state.IsConnected = true;
KeyboardDevices[device] = state;
}
}
NativeMethods.IOHIDDeviceRegisterInputValueCallback(device,
HandleDeviceValueReceived, IntPtr.Zero);
NativeMethods.IOHIDDeviceScheduleWithRunLoop(device, RunLoop, InputLoopMode);
}
}
void DeviceRemoved(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
{
if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse) &&
MouseDevices.ContainsKey(device))
{
Debug.Print("Mouse device {0} disconnected", device);
// Keep the device in case it comes back later on
MouseState state = MouseDevices[device];
state.IsConnected = false;
MouseDevices[device] = state;
}
if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard) &&
KeyboardDevices.ContainsKey(device))
{
Debug.Print("Keyboard device {0} disconnected", device);
// Keep the device in case it comes back later on
KeyboardState state = KeyboardDevices[device];
state.IsConnected = false;
KeyboardDevices[device] = state;
}
NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, null, IntPtr.Zero);
NativeMethods.IOHIDDeviceUnscheduleWithRunLoop(device, RunLoop, InputLoopMode);
}
void DeviceValueReceived(IntPtr context, IOReturn res, IntPtr sender, IOHIDValueRef val)
{
MouseState mouse;
KeyboardState keyboard;
if (MouseDevices.TryGetValue(sender, out mouse))
{
MouseDevices[sender] = UpdateMouse(mouse, val);
}
else if (KeyboardDevices.TryGetValue(sender, out keyboard))
{
KeyboardDevices[sender] = UpdateKeyboard(keyboard, val);
}
}
static MouseState UpdateMouse(MouseState state, IOHIDValueRef val)
{
IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
//double v_physical = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Physical);
//double v_calbrated = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Calibrated);
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
int usage = NativeMethods.IOHIDElementGetUsage(elem);
switch (page)
{
case HIDPage.GenericDesktop:
switch ((HIDUsageGD)usage)
{
case HIDUsageGD.X:
state.X += v_int;
break;
case HIDUsageGD.Y:
state.Y += v_int;
break;
case HIDUsageGD.Wheel:
state.WheelPrecise += v_int;
break;
}
break;
case HIDPage.Button:
state[OpenTK.Input.MouseButton.Left + usage - 1] = v_int == 1;
break;
}
return state;
}
static KeyboardState UpdateKeyboard(KeyboardState state, IOHIDValueRef val)
{
IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
int usage = NativeMethods.IOHIDElementGetUsage(elem);
switch (page)
{
case HIDPage.GenericDesktop:
case HIDPage.KeyboardOrKeypad:
int raw = (int)usage;
if (raw >= RawKeyMap.Length || raw < 0)
{
Debug.Print("[Warning] Key {0} not mapped.", raw);
return state;
}
Key key = RawKeyMap[raw];
state[key] = v_int != 0;
break;
}
return state;
}
#endregion
#region IInputDriver2 Members
public IMouseDriver2 MouseDriver { get { return this; } }
public IKeyboardDriver2 KeyboardDriver { get { return this; } }
public IGamePadDriver GamePadDriver { get { throw new NotImplementedException(); } }
#endregion
#region IMouseDriver2 Members
MouseState IMouseDriver2.GetState()
{
MouseState master = new MouseState();
foreach (KeyValuePair<IntPtr, MouseState> item in MouseDevices)
{
master.MergeBits(item.Value);
}
return master;
}
MouseState IMouseDriver2.GetState(int index)
{
IntPtr device;
if (MouseIndexToDevice.TryGetValue(index, out device))
{
return MouseDevices[device];
}
return new MouseState();
}
void IMouseDriver2.SetPosition(double x, double y)
{
CG.SetLocalEventsSuppressionInterval(0.0);
CG.WarpMouseCursorPosition(new Carbon.HIPoint(x, y));
}
#endregion
#region IKeyboardDriver2
KeyboardState IKeyboardDriver2.GetState()
{
KeyboardState master = new KeyboardState();
foreach (KeyValuePair<IntPtr, KeyboardState> item in KeyboardDevices)
{
master.MergeBits(item.Value);
}
return master;
}
KeyboardState IKeyboardDriver2.GetState(int index)
{
IntPtr device;
if (KeyboardIndexToDevice.TryGetValue(index, out device))
{
return KeyboardDevices[device];
}
return new KeyboardState();
}
string IKeyboardDriver2.GetDeviceName(int index)
{
IntPtr device;
if (KeyboardIndexToDevice.TryGetValue(index, out device))
{
IntPtr vendor_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDVendorIDKey);
IntPtr product_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductIDKey);
// Todo: find out the real vendor/product name from the relevant ids.
return String.Format("{0}:{1}", vendor_id, product_id);
}
return String.Empty;
}
#endregion
#region NativeMethods
class NativeMethods
{
const string hid = "/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit";
public static readonly CFString IOHIDVendorIDKey = CF.CFSTR("VendorID");
public static readonly CFString IOHIDVendorIDSourceKey = CF.CFSTR("VendorIDSource");
public static readonly CFString IOHIDProductIDKey = CF.CFSTR("ProductID");
public static readonly CFString IOHIDVersionNumberKey = CF.CFSTR("VersionNumber");
public static readonly CFString IOHIDManufacturerKey = CF.CFSTR("Manufacturer");
public static readonly CFString IOHIDProductKey = CF.CFSTR("Product");
public static readonly CFString IOHIDDeviceUsageKey = CF.CFSTR("DeviceUsage");
public static readonly CFString IOHIDDeviceUsagePageKey = CF.CFSTR("DeviceUsagePage");
public static readonly CFString IOHIDDeviceUsagePairsKey = CF.CFSTR("DeviceUsagePairs");
[DllImport(hid)]
public static extern IOHIDManagerRef IOHIDManagerCreate(
CFAllocatorRef allocator, IOOptionBits options) ;
// This routine will be called when a new (matching) device is connected.
[DllImport(hid)]
public static extern void IOHIDManagerRegisterDeviceMatchingCallback(
IOHIDManagerRef inIOHIDManagerRef,
IOHIDDeviceCallback inIOHIDDeviceCallback,
IntPtr inContext);
// This routine will be called when a (matching) device is disconnected.
[DllImport(hid)]
public static extern void IOHIDManagerRegisterDeviceRemovalCallback(
IOHIDManagerRef inIOHIDManagerRef,
IOHIDDeviceCallback inIOHIDDeviceCallback,
IntPtr inContext);
[DllImport(hid)]
public static extern void IOHIDManagerScheduleWithRunLoop(
IOHIDManagerRef inIOHIDManagerRef,
CFRunLoop inCFRunLoop,
CFString inCFRunLoopMode);
[DllImport(hid)]
public static extern void IOHIDManagerSetDeviceMatching(
IOHIDManagerRef manager,
CFDictionaryRef matching) ;
[DllImport(hid)]
public static extern IOReturn IOHIDManagerOpen(
IOHIDManagerRef manager,
IOOptionBits options) ;
[DllImport(hid)]
public static extern IOReturn IOHIDDeviceOpen(
IOHIDDeviceRef manager,
IOOptionBits opts);
[DllImport(hid)]
public static extern CFTypeRef IOHIDDeviceGetProperty(
IOHIDDeviceRef device,
CFStringRef key);
[DllImport(hid)]
public static extern bool IOHIDDeviceConformsTo(
IOHIDDeviceRef inIOHIDDeviceRef, // IOHIDDeviceRef for the HID device
HIDPage inUsagePage, // the usage page to test conformance with
int inUsage); // the usage to test conformance with
[DllImport(hid)]
public static extern void IOHIDDeviceRegisterInputValueCallback(
IOHIDDeviceRef device,
IOHIDValueCallback callback,
IntPtr context);
[DllImport(hid)]
public static extern void IOHIDDeviceScheduleWithRunLoop(
IOHIDDeviceRef device,
CFRunLoop inCFRunLoop,
CFString inCFRunLoopMode);
[DllImport(hid)]
public static extern void IOHIDDeviceUnscheduleWithRunLoop(
IOHIDDeviceRef device,
CFRunLoop inCFRunLoop,
CFString inCFRunLoopMode);
[DllImport(hid)]
public static extern IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef @value);
[DllImport(hid)]
public static extern CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef @value);
[DllImport(hid)]
public static extern double IOHIDValueGetScaledValue(
IOHIDValueRef @value,
IOHIDValueScaleType type) ;
[DllImport(hid)]
public static extern int IOHIDElementGetUsage(IOHIDElementRef elem);
[DllImport(hid)]
public static extern HIDPage IOHIDElementGetUsagePage(IOHIDElementRef elem);
public delegate void IOHIDDeviceCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDDeviceRef device);
public delegate void IOHIDValueCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDValueRef val);
}
enum IOHIDValueScaleType
{
Physical, // [device min, device max]
Calibrated // [-1, +1]
}
enum HIDPage
{
Undefined = 0x00,
GenericDesktop = 0x01,
Simulation = 0x02,
VR = 0x03,
Sport = 0x04,
Game = 0x05,
/* Reserved 0x06 */
KeyboardOrKeypad = 0x07, /* USB Device Class Definition for Human Interface Devices (HID). Note: the usage type for all key codes is Selector (Sel). */
LEDs = 0x08,
Button = 0x09,
Ordinal = 0x0A,
Telephony = 0x0B,
Consumer = 0x0C,
Digitizer = 0x0D,
/* Reserved 0x0E */
PID = 0x0F, /* USB Physical Interface Device definitions for force feedback and related devices. */
Unicode = 0x10,
/* Reserved 0x11 - 0x13 */
AlphanumericDisplay = 0x14,
/* Reserved 0x15 - 0x7F */
/* Monitor 0x80 - 0x83 USB Device Class Definition for Monitor Devices */
/* Power 0x84 - 0x87 USB Device Class Definition for Power Devices */
PowerDevice = 0x84, /* Power Device Page */
BatterySystem = 0x85, /* Battery System Page */
/* Reserved 0x88 - 0x8B */
BarCodeScanner = 0x8C, /* (Point of Sale) USB Device Class Definition for Bar Code Scanner Devices */
WeighingDevice = 0x8D, /* (Point of Sale) USB Device Class Definition for Weighing Devices */
Scale = 0x8D, /* (Point of Sale) USB Device Class Definition for Scale Devices */
MagneticStripeReader = 0x8E,
/* ReservedPointofSalepages 0x8F */
CameraControl = 0x90, /* USB Device Class Definition for Image Class Devices */
Arcade = 0x91, /* OAAF Definitions for arcade and coinop related Devices */
/* Reserved 0x92 - 0xFEFF */
/* VendorDefined 0xFF00 - 0xFFFF */
VendorDefinedStart = 0xFF00
}
// Generic desktop usage
enum HIDUsageGD
{
Pointer = 0x01, /* Physical Collection */
Mouse = 0x02, /* Application Collection */
/* 0x03 Reserved */
Joystick = 0x04, /* Application Collection */
GamePad = 0x05, /* Application Collection */
Keyboard = 0x06, /* Application Collection */
Keypad = 0x07, /* Application Collection */
MultiAxisController = 0x08, /* Application Collection */
/* 0x09 - 0x2F Reserved */
X = 0x30, /* Dynamic Value */
Y = 0x31, /* Dynamic Value */
Z = 0x32, /* Dynamic Value */
Rx = 0x33, /* Dynamic Value */
Ry = 0x34, /* Dynamic Value */
Rz = 0x35, /* Dynamic Value */
Slider = 0x36, /* Dynamic Value */
Dial = 0x37, /* Dynamic Value */
Wheel = 0x38, /* Dynamic Value */
Hatswitch = 0x39, /* Dynamic Value */
CountedBuffer = 0x3A, /* Logical Collection */
ByteCount = 0x3B, /* Dynamic Value */
MotionWakeup = 0x3C, /* One-Shot Control */
Start = 0x3D, /* On/Off Control */
Select = 0x3E, /* On/Off Control */
/* 0x3F Reserved */
Vx = 0x40, /* Dynamic Value */
Vy = 0x41, /* Dynamic Value */
Vz = 0x42, /* Dynamic Value */
Vbrx = 0x43, /* Dynamic Value */
Vbry = 0x44, /* Dynamic Value */
Vbrz = 0x45, /* Dynamic Value */
Vno = 0x46, /* Dynamic Value */
/* 0x47 - 0x7F Reserved */
SystemControl = 0x80, /* Application Collection */
SystemPowerDown = 0x81, /* One-Shot Control */
SystemSleep = 0x82, /* One-Shot Control */
SystemWakeUp = 0x83, /* One-Shot Control */
SystemContextMenu = 0x84, /* One-Shot Control */
SystemMainMenu = 0x85, /* One-Shot Control */
SystemAppMenu = 0x86, /* One-Shot Control */
SystemMenuHelp = 0x87, /* One-Shot Control */
SystemMenuExit = 0x88, /* One-Shot Control */
SystemMenu = 0x89, /* Selector */
SystemMenuRight = 0x8A, /* Re-Trigger Control */
SystemMenuLeft = 0x8B, /* Re-Trigger Control */
SystemMenuUp = 0x8C, /* Re-Trigger Control */
SystemMenuDown = 0x8D, /* Re-Trigger Control */
/* 0x8E - 0x8F Reserved */
DPadUp = 0x90, /* On/Off Control */
DPadDown = 0x91, /* On/Off Control */
DPadRight = 0x92, /* On/Off Control */
DPadLeft = 0x93, /* On/Off Control */
/* 0x94 - 0xFFFF Reserved */
Reserved = 0xFFFF
}
enum HIDButton
{
Button_1 = 0x01, /* (primary/trigger) */
Button_2 = 0x02, /* (secondary) */
Button_3 = 0x03, /* (tertiary) */
Button_4 = 0x04, /* 4th button */
/* ... */
Button_65535 = 0xFFFF
}
enum HIDKey
{
ErrorRollOver = 0x01, /* ErrorRollOver */
POSTFail = 0x02, /* POSTFail */
ErrorUndefined = 0x03, /* ErrorUndefined */
A = 0x04, /* a or A */
B = 0x05, /* b or B */
C = 0x06, /* c or C */
D = 0x07, /* d or D */
E = 0x08, /* e or E */
F = 0x09, /* f or F */
G = 0x0A, /* g or G */
H = 0x0B, /* h or H */
I = 0x0C, /* i or I */
J = 0x0D, /* j or J */
K = 0x0E, /* k or K */
L = 0x0F, /* l or L */
M = 0x10, /* m or M */
N = 0x11, /* n or N */
O = 0x12, /* o or O */
P = 0x13, /* p or P */
Q = 0x14, /* q or Q */
R = 0x15, /* r or R */
S = 0x16, /* s or S */
T = 0x17, /* t or T */
U = 0x18, /* u or U */
V = 0x19, /* v or V */
W = 0x1A, /* w or W */
X = 0x1B, /* x or X */
Y = 0x1C, /* y or Y */
Z = 0x1D, /* z or Z */
Number1 = 0x1E, /* 1 or ! */
Number2 = 0x1F, /* 2 or @ */
Number3 = 0x20, /* 3 or # */
Number4 = 0x21, /* 4 or $ */
Number5 = 0x22, /* 5 or % */
Number6 = 0x23, /* 6 or ^ */
Number7 = 0x24, /* 7 or & */
Number8 = 0x25, /* 8 or * */
Number9 = 0x26, /* 9 or ( */
Number0 = 0x27, /* 0 or ) */
ReturnOrEnter = 0x28, /* Return (Enter) */
Escape = 0x29, /* Escape */
DeleteOrBackspace = 0x2A, /* Delete (Backspace) */
Tab = 0x2B, /* Tab */
Spacebar = 0x2C, /* Spacebar */
Hyphen = 0x2D, /* - or _ */
EqualSign = 0x2E, /* = or + */
OpenBracket = 0x2F, /* [ or { */
CloseBracket = 0x30, /* ] or } */
Backslash = 0x31, /* \ or | */
NonUSPound = 0x32, /* Non-US # or _ */
Semicolon = 0x33, /* ; or : */
Quote = 0x34, /* ' or " */
GraveAccentAndTilde = 0x35, /* Grave Accent and Tilde */
Comma = 0x36, /* , or < */
Period = 0x37, /* . or > */
Slash = 0x38, /* / or ? */
CapsLock = 0x39, /* Caps Lock */
F1 = 0x3A, /* F1 */
F2 = 0x3B, /* F2 */
F3 = 0x3C, /* F3 */
F4 = 0x3D, /* F4 */
F5 = 0x3E, /* F5 */
F6 = 0x3F, /* F6 */
F7 = 0x40, /* F7 */
F8 = 0x41, /* F8 */
F9 = 0x42, /* F9 */
F10 = 0x43, /* F10 */
F11 = 0x44, /* F11 */
F12 = 0x45, /* F12 */
PrintScreen = 0x46, /* Print Screen */
ScrollLock = 0x47, /* Scroll Lock */
Pause = 0x48, /* Pause */
Insert = 0x49, /* Insert */
Home = 0x4A, /* Home */
PageUp = 0x4B, /* Page Up */
DeleteForward = 0x4C, /* Delete Forward */
End = 0x4D, /* End */
PageDown = 0x4E, /* Page Down */
RightArrow = 0x4F, /* Right Arrow */
LeftArrow = 0x50, /* Left Arrow */
DownArrow = 0x51, /* Down Arrow */
UpArrow = 0x52, /* Up Arrow */
KeypadNumLock = 0x53, /* Keypad NumLock or Clear */
KeypadSlash = 0x54, /* Keypad / */
KeypadAsterisk = 0x55, /* Keypad * */
KeypadHyphen = 0x56, /* Keypad - */
KeypadPlus = 0x57, /* Keypad + */
KeypadEnter = 0x58, /* Keypad Enter */
Keypad1 = 0x59, /* Keypad 1 or End */
Keypad2 = 0x5A, /* Keypad 2 or Down Arrow */
Keypad3 = 0x5B, /* Keypad 3 or Page Down */
Keypad4 = 0x5C, /* Keypad 4 or Left Arrow */
Keypad5 = 0x5D, /* Keypad 5 */
Keypad6 = 0x5E, /* Keypad 6 or Right Arrow */
Keypad7 = 0x5F, /* Keypad 7 or Home */
Keypad8 = 0x60, /* Keypad 8 or Up Arrow */
Keypad9 = 0x61, /* Keypad 9 or Page Up */
Keypad0 = 0x62, /* Keypad 0 or Insert */
KeypadPeriod = 0x63, /* Keypad . or Delete */
NonUSBackslash = 0x64, /* Non-US \ or | */
Application = 0x65, /* Application */
Power = 0x66, /* Power */
KeypadEqualSign = 0x67, /* Keypad = */
F13 = 0x68, /* F13 */
F14 = 0x69, /* F14 */
F15 = 0x6A, /* F15 */
F16 = 0x6B, /* F16 */
F17 = 0x6C, /* F17 */
F18 = 0x6D, /* F18 */
F19 = 0x6E, /* F19 */
F20 = 0x6F, /* F20 */
F21 = 0x70, /* F21 */
F22 = 0x71, /* F22 */
F23 = 0x72, /* F23 */
F24 = 0x73, /* F24 */
Execute = 0x74, /* Execute */
Help = 0x75, /* Help */
Menu = 0x76, /* Menu */
Select = 0x77, /* Select */
Stop = 0x78, /* Stop */
Again = 0x79, /* Again */
Undo = 0x7A, /* Undo */
Cut = 0x7B, /* Cut */
Copy = 0x7C, /* Copy */
Paste = 0x7D, /* Paste */
Find = 0x7E, /* Find */
Mute = 0x7F, /* Mute */
VolumeUp = 0x80, /* Volume Up */
VolumeDown = 0x81, /* Volume Down */
LockingCapsLock = 0x82, /* Locking Caps Lock */
LockingNumLock = 0x83, /* Locking Num Lock */
LockingScrollLock = 0x84, /* Locking Scroll Lock */
KeypadComma = 0x85, /* Keypad Comma */
KeypadEqualSignAS400 = 0x86, /* Keypad Equal Sign for AS/400 */
International1 = 0x87, /* International1 */
International2 = 0x88, /* International2 */
International3 = 0x89, /* International3 */
International4 = 0x8A, /* International4 */
International5 = 0x8B, /* International5 */
International6 = 0x8C, /* International6 */
International7 = 0x8D, /* International7 */
International8 = 0x8E, /* International8 */
International9 = 0x8F, /* International9 */
LANG1 = 0x90, /* LANG1 */
LANG2 = 0x91, /* LANG2 */
LANG3 = 0x92, /* LANG3 */
LANG4 = 0x93, /* LANG4 */
LANG5 = 0x94, /* LANG5 */
LANG6 = 0x95, /* LANG6 */
LANG7 = 0x96, /* LANG7 */
LANG8 = 0x97, /* LANG8 */
LANG9 = 0x98, /* LANG9 */
AlternateErase = 0x99, /* AlternateErase */
SysReqOrAttention = 0x9A, /* SysReq/Attention */
Cancel = 0x9B, /* Cancel */
Clear = 0x9C, /* Clear */
Prior = 0x9D, /* Prior */
Return = 0x9E, /* Return */
Separator = 0x9F, /* Separator */
Out = 0xA0, /* Out */
Oper = 0xA1, /* Oper */
ClearOrAgain = 0xA2, /* Clear/Again */
CrSelOrProps = 0xA3, /* CrSel/Props */
ExSel = 0xA4, /* ExSel */
/* 0xA5-0xDF Reserved */
LeftControl = 0xE0, /* Left Control */
LeftShift = 0xE1, /* Left Shift */
LeftAlt = 0xE2, /* Left Alt */
LeftGUI = 0xE3, /* Left GUI */
RightControl = 0xE4, /* Right Control */
RightShift = 0xE5, /* Right Shift */
RightAlt = 0xE6, /* Right Alt */
RightGUI = 0xE7, /* Right GUI */
/* 0xE8-0xFFFF Reserved */
//_Reserved = 0xFFFF
}
// Maps HIDKey to OpenTK.Input.Key.
static readonly Key[] RawKeyMap = new Key[]
{
Key.Unknown,
Key.Unknown, /* ErrorRollOver */
Key.Unknown, /* POSTFail */
Key.Unknown, /* ErrorUndefined */
Key.A, /* a or A */
Key.B, /* b or B */
Key.C, /* c or C */
Key.D, /* d or D */
Key.E, /* e or E */
Key.F, /* f or F */
Key.G, /* g or G */
Key.H, /* h or H */
Key.I, /* i or I */
Key.J, /* j or J */
Key.K, /* k or K */
Key.L, /* l or L */
Key.M, /* m or M */
Key.N, /* n or N */
Key.O, /* o or O */
Key.P, /* p or P */
Key.Q, /* q or Q */
Key.R, /* r or R */
Key.S, /* s or S */
Key.T, /* t or T */
Key.U, /* u or U */
Key.V, /* v or V */
Key.W, /* w or W */
Key.X, /* x or X */
Key.Y, /* y or Y */
Key.Z, /* z or Z */
Key.Number1, /* 1 or ! */
Key.Number2, /* 2 or @ */
Key.Number3, /* 3 or # */
Key.Number4, /* 4 or $ */
Key.Number5, /* 5 or % */
Key.Number6, /* 6 or ^ */
Key.Number7, /* 7 or & */
Key.Number8, /* 8 or * */
Key.Number9, /* 9 or ( */
Key.Number0, /* 0 or ) */
Key.Enter, /* Return (Enter) */
Key.Escape, /* Escape */
Key.BackSpace, /* Delete (Backspace) */
Key.Tab, /* Tab */
Key.Space, /* Spacebar */
Key.Minus, /* - or _ */
Key.Plus, /* = or + */
Key.BracketLeft, /* [ or { */
Key.BracketRight, /* ] or } */
Key.BackSlash, /* \ or | */
Key.Minus, /* Non-US # or _ */
Key.Semicolon, /* ; or : */
Key.Quote, /* ' or " */
Key.Tilde, /* Grave Accent and Tilde */
Key.Comma, /* , or < */
Key.Period, /* . or > */
Key.Slash, /* / or ? */
Key.CapsLock, /* Caps Lock */
Key.F1, /* F1 */
Key.F2, /* F2 */
Key.F3, /* F3 */
Key.F4, /* F4 */
Key.F5, /* F5 */
Key.F6, /* F6 */
Key.F7, /* F7 */
Key.F8, /* F8 */
Key.F9, /* F9 */
Key.F10, /* F10 */
Key.F11, /* F11 */
Key.F12, /* F12 */
Key.PrintScreen, /* Print Screen */
Key.ScrollLock, /* Scroll Lock */
Key.Pause, /* Pause */
Key.Insert, /* Insert */
Key.Home, /* Home */
Key.PageUp, /* Page Up */
Key.Delete, /* Delete Forward */
Key.End, /* End */
Key.PageDown, /* Page Down */
Key.Right, /* Right Arrow */
Key.Left, /* Left Arrow */
Key.Down, /* Down Arrow */
Key.Up, /* Up Arrow */
Key.NumLock, /* Keypad NumLock or Clear */
Key.KeypadDivide, /* Keypad / */
Key.KeypadMultiply, /* Keypad * */
Key.KeypadMinus, /* Keypad - */
Key.KeypadPlus, /* Keypad + */
Key.KeypadEnter, /* Keypad Enter */
Key.Keypad1, /* Keypad 1 or End */
Key.Keypad2, /* Keypad 2 or Down Arrow */
Key.Keypad3, /* Keypad 3 or Page Down */
Key.Keypad4, /* Keypad 4 or Left Arrow */
Key.Keypad5, /* Keypad 5 */
Key.Keypad6, /* Keypad 6 or Right Arrow */
Key.Keypad7, /* Keypad 7 or Home */
Key.Keypad8, /* Keypad 8 or Up Arrow */
Key.Keypad9, /* Keypad 9 or Page Up */
Key.Keypad0, /* Keypad 0 or Insert */
Key.KeypadDecimal, /* Keypad . or Delete */
Key.BackSlash, /* Non-US \ or | */
Key.Unknown, /* Application */
Key.Unknown, /* Power */
Key.Unknown, /* Keypad = */
Key.F13, /* F13 */
Key.F14, /* F14 */
Key.F15, /* F15 */
Key.F16, /* F16 */
Key.F17, /* F17 */
Key.F18, /* F18 */
Key.F19, /* F19 */
Key.F20, /* F20 */
Key.F21, /* F21 */
Key.F22, /* F22 */
Key.F23, /* F23 */
Key.F24, /* F24 */
Key.Unknown, /* Execute */
Key.Unknown, /* Help */
Key.Menu, /* Menu */
Key.Unknown, /* Select */
Key.Unknown, /* Stop */
Key.Unknown, /* Again */
Key.Unknown, /* Undo */
Key.Unknown, /* Cut */
Key.Unknown, /* Copy */
Key.Unknown, /* Paste */
Key.Unknown, /* Find */
Key.Unknown, /* Mute */
Key.Unknown, /* Volume Up */
Key.Unknown, /* Volume Down */
Key.CapsLock, /* Locking Caps Lock */
Key.NumLock , /* Locking Num Lock */
Key.ScrollLock, /* Locking Scroll Lock */
Key.KeypadDecimal, /* Keypad Comma */
Key.Unknown, /* Keypad Equal Sign for AS/400 */
Key.Unknown, /* International1 */
Key.Unknown, /* International2 */
Key.Unknown, /* International3 */
Key.Unknown, /* International4 */
Key.Unknown, /* International5 */
Key.Unknown, /* International6 */
Key.Unknown, /* International7 */
Key.Unknown, /* International8 */
Key.Unknown, /* International9 */
Key.Unknown, /* LANG1 */
Key.Unknown, /* LANG2 */
Key.Unknown, /* LANG3 */
Key.Unknown, /* LANG4 */
Key.Unknown, /* LANG5 */
Key.Unknown, /* LANG6 */
Key.Unknown, /* LANG7 */
Key.Unknown, /* LANG8 */
Key.Unknown, /* LANG9 */
Key.Unknown, /* AlternateErase */
Key.Unknown, /* SysReq/Attention */
Key.Unknown, /* Cancel */
Key.Unknown, /* Clear */
Key.Unknown, /* Prior */
Key.Enter, /* Return */
Key.Unknown, /* Separator */
Key.Unknown, /* Out */
Key.Unknown, /* Oper */
Key.Unknown, /* Clear/Again */
Key.Unknown, /* CrSel/Props */
Key.Unknown, /* ExSel */
/* 0xA5-0xDF Reserved */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Key.LControl, /* Left Control */
Key.LShift, /* Left Shift */
Key.LAlt, /* Left Alt */
Key.LWin, /* Left GUI */
Key.RControl, /* Right Control */
Key.RShift, /* Right Shift */
Key.RAlt, /* Right Alt */
Key.RWin, /* Right GUI */
/* 0xE8-0xFFFF Reserved */
};
#endregion
}
}

View file

@ -1,3 +1,31 @@
#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
// Created by Erik Ylvisaker on 3/17/08.
using System;

View file

@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK.Input;
namespace OpenTK.Platform.MacOS
{
@ -35,6 +36,12 @@ namespace OpenTK.Platform.MacOS
class MacOSFactory : IPlatformFactory
{
#region Fields
readonly IInputDriver2 InputDriver = new HIDInput();
#endregion
#region IPlatformFactory Members
public virtual INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
@ -55,7 +62,7 @@ namespace OpenTK.Platform.MacOS
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
return new AglContext(handle, window, shareContext);
}
}
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
@ -70,9 +77,14 @@ namespace OpenTK.Platform.MacOS
return new MacOSGraphicsMode();
}
public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
throw new NotImplementedException();
return InputDriver.KeyboardDriver;
}
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
return InputDriver.MouseDriver;
}
#endregion

View file

@ -1,23 +1,155 @@
#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;
using System.Text;
using OpenTK.Graphics;
namespace OpenTK.Platform.MacOS
{
using Graphics;
using Carbon;
class MacOSGraphicsMode : IGraphicsMode
class MacOSGraphicsMode : IGraphicsMode
{
#region IGraphicsMode Members
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo)
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo)
{
GraphicsMode gfx = new GraphicsMode((IntPtr)1, color, depth, stencil, samples,
accum, buffers, stereo);
IntPtr pixelformat = SelectPixelFormat(color, depth, stencil, samples, accum, buffers, stereo);
return GetGraphicsModeFromPixelFormat(pixelformat);
}
System.Diagnostics.Debug.Print("Created dummy graphics mode.");
#endregion
return gfx;
#region Private Members
GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat)
{
int r, g, b, a;
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_RED_SIZE, out r);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_GREEN_SIZE, out g);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, out b);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, out a);
int ar, ag, ab, aa;
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, out aa);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, out ar);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_ACCUM_GREEN_SIZE, out ag);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, out ab);
int depth, stencil, samples, buffers, stereo;
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, out depth);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, out stencil);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, out samples);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER, out buffers);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_STEREO, out stereo);
return new GraphicsMode(pixelformat, new ColorFormat(r, g, b, a),
depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0);
}
IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo)
{
List<int> attribs = new List<int>();
Debug.Print("Bits per pixel: {0}", color.BitsPerPixel);
if (color.BitsPerPixel > 0)
{
if (!color.IsIndexed)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_RGBA);
}
attribs.Add((int)Agl.PixelFormatAttribute.AGL_RED_SIZE);
attribs.Add(color.Red);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_GREEN_SIZE);
attribs.Add(color.Green);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_BLUE_SIZE);
attribs.Add(color.Blue);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_ALPHA_SIZE);
attribs.Add(color.Alpha);
}
Debug.Print("Depth: {0}", depth);
if (depth > 0)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_DEPTH_SIZE);
attribs.Add(depth);
}
if (buffers > 1)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
}
if (stencil > 1)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STENCIL_SIZE);
attribs.Add(stencil);
}
if (accum.BitsPerPixel > 0)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE);
attribs.Add(accum.Alpha);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE);
attribs.Add(accum.Blue);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_ACCUM_GREEN_SIZE);
attribs.Add(accum.Green);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE);
attribs.Add(accum.Red);
}
if (samples > 0)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB);
attribs.Add(1);
attribs.Add((int)Agl.PixelFormatAttribute.AGL_SAMPLES_ARB);
attribs.Add(samples);
}
if (stereo)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO);
}
attribs.Add(0);
attribs.Add(0);
IntPtr pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
if (pixelformat == IntPtr.Zero)
{
throw new GraphicsModeException(String.Format(
"[Error] Failed to select GraphicsMode, error {0}.", Agl.GetError()));
}
return pixelformat;
}
#endregion

View file

@ -1,3 +1,32 @@
#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
// Created by Erik Ylvisaker on 3/17/08.
using System;
using System.Collections.Generic;
using System.Text;
@ -12,7 +41,7 @@ namespace OpenTK.Platform.MacOS
public MacOSKeyMap()
{
// comments indicate members of the Key enum that are missing
Add(MacOSKeyCode.A, Key.A);
// AltLeft
// AltRight
@ -127,7 +156,7 @@ namespace OpenTK.Platform.MacOS
Add(MacOSKeyCode.X, Key.X);
Add(MacOSKeyCode.Y, Key.Y);
Add(MacOSKeyCode.Z, Key.Z);
}
}
}

View file

@ -1,23 +1,43 @@
#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;
using System.Drawing;
using OpenTK.Platform.MacOS.Carbon;
namespace OpenTK.Platform.MacOS
{
using System.Drawing;
using Carbon;
class QuartzDisplayDeviceDriver : IDisplayDeviceDriver
sealed class QuartzDisplayDeviceDriver : DisplayDeviceBase
{
static object display_lock = new object();
static Dictionary<DisplayDevice, IntPtr> displayMap =
new Dictionary<DisplayDevice, IntPtr>();
static IntPtr mainDisplay;
internal static IntPtr MainDisplay { get { return mainDisplay; } }
static QuartzDisplayDeviceDriver()
public QuartzDisplayDeviceDriver()
{
lock (display_lock)
{
@ -30,158 +50,149 @@ namespace OpenTK.Platform.MacOS
const int maxDisplayCount = 20;
IntPtr[] displays = new IntPtr[maxDisplayCount];
int displayCount;
unsafe
{
fixed(IntPtr* displayPtr = displays)
fixed (IntPtr* displayPtr = displays)
{
CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
}
}
Debug.Print("CoreGraphics reported {0} display(s).", displayCount);
Debug.Indent();
for (int i = 0; i < displayCount; i++)
{
IntPtr currentDisplay = displays[i];
// according to docs, first element in the array is always the
// main display.
bool primary = (i == 0);
if (primary)
mainDisplay = currentDisplay;
// gets current settings
int currentWidth = CG.DisplayPixelsWide(currentDisplay);
int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
CFArray displayModes = new CFArray(displayModesPtr);
Debug.Print("Supports {0} display modes.", displayModes.Count);
DisplayResolution opentk_dev_current_res = null;
List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
CFDictionary currentMode = new CFDictionary(currentModePtr);
for (int j = 0; j < displayModes.Count; j++)
{
CFDictionary dict = new CFDictionary(displayModes[j]);
int width = (int) dict.GetNumberValue("Width");
int height = (int) dict.GetNumberValue("Height");
int bpp = (int) dict.GetNumberValue("BitsPerPixel");
int width = (int)dict.GetNumberValue("Width");
int height = (int)dict.GetNumberValue("Height");
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
double freq = dict.GetNumberValue("RefreshRate");
bool current = currentMode.Ref == dict.Ref;
//if (current) Debug.Write(" * ");
//else Debug.Write(" ");
//Debug.Print("Mode {0} is {1}x{2}x{3} @ {4}.", j, width, height, bpp, freq);
DisplayResolution thisRes = new DisplayResolution(0, 0, width, height, bpp, (float)freq);
opentk_dev_available_res.Add(thisRes);
if (current)
opentk_dev_current_res = thisRes;
}
HIRect bounds = CG.DisplayBounds(currentDisplay);
Rectangle newRect = new Rectangle((int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
Debug.Print("Display {0} bounds: {1}", i, newRect);
DisplayDevice opentk_dev = new DisplayDevice(opentk_dev_current_res,
primary, opentk_dev_available_res, newRect, currentDisplay);
HIRect bounds = CG.DisplayBounds(currentDisplay);
Rectangle newRect = new Rectangle(
(int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
AvailableDevices.Add(opentk_dev);
Debug.Print("Display {0} bounds: {1}", i, newRect);
DisplayDevice opentk_dev =
new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res, newRect);
displayMap.Add(opentk_dev, currentDisplay);
if (primary)
Primary = opentk_dev;
}
Debug.Unindent();
}
}
internal static IntPtr HandleTo(DisplayDevice displayDevice)
{
if (displayMap.ContainsKey(displayDevice))
return displayMap[displayDevice];
else
return IntPtr.Zero;
}
static internal IntPtr HandleTo(DisplayDevice displayDevice)
{
return (IntPtr)displayDevice.Id;
}
#region IDisplayDeviceDriver Members
Dictionary<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
List<IntPtr> displaysCaptured = new List<IntPtr>();
public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
{
IntPtr display = displayMap[device];
IntPtr currentModePtr = CG.DisplayCurrentMode(display);
public sealed override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
{
IntPtr display = HandleTo(device);
IntPtr currentModePtr = CG.DisplayCurrentMode(display);
if (storedModes.ContainsKey(display) == false)
{
storedModes.Add(display, currentModePtr);
storedModes.Add(display, currentModePtr);
}
IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
CFArray displayModes = new CFArray(displayModesPtr);
for (int j = 0; j < displayModes.Count; j++)
{
CFDictionary dict = new CFDictionary(displayModes[j]);
int width = (int)dict.GetNumberValue("Width");
int height = (int)dict.GetNumberValue("Height");
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
double freq = dict.GetNumberValue("RefreshRate");
if (width == resolution.Width &&
height == resolution.Height &&
bpp == resolution.BitsPerPixel &&
System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
if (width == resolution.Width && height == resolution.Height && bpp == resolution.BitsPerPixel && System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
{
if (displaysCaptured.Contains(display) == false)
{
CG.DisplayCapture(display);
}
Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
CG.DisplaySwitchToMode(display, displayModes[j]);
return true;
}
}
return false;
}
public bool TryRestoreResolution(DisplayDevice device)
public sealed override bool TryRestoreResolution(DisplayDevice device)
{
IntPtr display = displayMap[device];
IntPtr display = HandleTo(device);
if (storedModes.ContainsKey(display))
{
Debug.Print("Restoring resolution.");
CG.DisplaySwitchToMode(display, storedModes[display]);
CG.DisplayRelease(display);
displaysCaptured.Remove(display);
return true;
}
return false;
}
#endregion
}
}
}

View file

@ -9,7 +9,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;

View file

@ -59,6 +59,7 @@ namespace OpenTK.Platform.Windows
using RECT = OpenTK.Platform.Windows.Win32Rectangle;
using WNDPROC = System.IntPtr;
using LPDEVMODE = DeviceMode;
using HDEVNOTIFY = System.IntPtr;
using HRESULT = System.IntPtr;
using HMONITOR = System.IntPtr;
@ -349,7 +350,7 @@ namespace OpenTK.Platform.Windows
#region GetMessage
/// <summary>
/// Low-level WINAPI function that retriives the next message in the queue.
/// Low-level WINAPI function that retrieves the next message in the queue.
/// </summary>
/// <param name="msg">The pending message (if any) is stored here.</param>
/// <param name="windowHandle">Not used</param>
@ -845,12 +846,22 @@ namespace OpenTK.Platform.Windows
#endregion
[DllImport("user32.dll", SetLastError=true)]
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL SetForegroundWindow(HWND hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL BringWindowToTop(HWND hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL SetParent(HWND child, HWND newParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern HDEVNOTIFY RegisterDeviceNotification(HANDLE hRecipient,
LPVOID NotificationFilter, DeviceNotification Flags);
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL UnregisterDeviceNotification(HDEVNOTIFY Handle);
#endregion
#region Display settings
@ -951,6 +962,18 @@ namespace OpenTK.Platform.Windows
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr SetFocus(IntPtr hwnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int ShowCursor(bool show);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool ClipCursor(ref RECT rcClip);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool ClipCursor(IntPtr rcClip);
[DllImport("user32.dll")]
public static extern bool SetCursorPos(int X, int Y);
#region Async input
#region GetCursorPos
@ -966,7 +989,7 @@ namespace OpenTK.Platform.Windows
/// <para>The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with the HDESK returned by OpenInputDesktop to switch to that desktop.</para>
/// </remarks>
[DllImport("user32.dll", SetLastError = true), SuppressUnmanagedCodeSecurity]
internal static extern BOOL GetCursorPos(ref Point point);
internal static extern BOOL GetCursorPos(ref POINT point);
#endregion
@ -1344,17 +1367,6 @@ namespace OpenTK.Platform.Windows
/// <remarks>
/// GetRawInputData gets the raw input one RawInput structure at a time. In contrast, GetRawInputBuffer gets an array of RawInput structures.
/// </remarks>
[CLSCompliant(false)]
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll", SetLastError = true)]
internal static extern UINT GetRawInputData(
HRAWINPUT RawInput,
GetRawInputDataEnum Command,
[Out] LPVOID Data,
[In, Out] ref UINT Size,
UINT SizeHeader
);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll", SetLastError = true)]
internal static extern INT GetRawInputData(
@ -1386,17 +1398,6 @@ namespace OpenTK.Platform.Windows
/// <remarks>
/// GetRawInputData gets the raw input one RawInput structure at a time. In contrast, GetRawInputBuffer gets an array of RawInput structures.
/// </remarks>
[CLSCompliant(false)]
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll", SetLastError = true)]
internal static extern UINT GetRawInputData(
HRAWINPUT RawInput,
GetRawInputDataEnum Command,
/*[MarshalAs(UnmanagedType.LPStruct)]*/ [Out] out RawInput Data,
[In, Out] ref UINT Size,
UINT SizeHeader
);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll", SetLastError = true)]
internal static extern INT GetRawInputData(
@ -1407,6 +1408,16 @@ namespace OpenTK.Platform.Windows
INT SizeHeader
);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("user32.dll", SetLastError = true)]
unsafe internal static extern INT GetRawInputData(
HRAWINPUT RawInput,
GetRawInputDataEnum Command,
RawInput* Data,
[In, Out] ref INT Size,
INT SizeHeader
);
#endregion
#region IntPtr NextRawInputStructure(IntPtr data)
@ -1478,7 +1489,7 @@ namespace OpenTK.Platform.Windows
#region --- Constants ---
internal struct Constants
static class Constants
{
// Found in winuser.h
internal const int KEYBOARD_OVERRUN_MAKE_CODE = 0xFF;
@ -1565,6 +1576,8 @@ namespace OpenTK.Platform.Windows
// (found in winuser.h)
internal const int ENUM_REGISTRY_SETTINGS = -2;
internal const int ENUM_CURRENT_SETTINGS = -1;
internal static readonly IntPtr MESSAGE_ONLY = new IntPtr(-3);
}
#endregion
@ -2222,25 +2235,11 @@ namespace OpenTK.Platform.Windows
/// <para>To get device specific information, call GetRawInputDeviceInfo with the hDevice from RAWINPUTHEADER.</para>
/// <para>Raw input is available only when the application calls RegisterRawInputDevices with valid device specifications.</para>
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
internal struct RawInput
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct RawInput
{
internal RawInputHeader Header;
internal RawInputData Data;
internal byte[] ToByteArray()
{
unsafe
{
byte[] dump = new byte[API.RawInputSize];
fixed (RawInputDeviceType* ptr = &Header.Type)
{
for (int i = 0; i < API.RawInputSize; i++)
dump[i] = *((byte*)ptr + i);
return dump;
}
}
}
public RawInputHeader Header;
public RawInputData Data;
}
[StructLayout(LayoutKind.Explicit)]
@ -2341,38 +2340,9 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Contains information about the state of the mouse.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack=1)]
[StructLayout(LayoutKind.Explicit)]
internal struct RawMouse
{
//internal RawMouseFlags Flags; // USHORT in winuser.h, but only INT works -- USHORT returns 0.
USHORT flags;
byte for_alignment; // Not used -- used for alignment
/// <summary>
/// Reserved.
/// </summary>
//ULONG Buttons;
internal USHORT buttonFlags;
/// <summary>
/// If usButtonFlags is RI_MOUSE_WHEEL, this member is a signed value that specifies the wheel delta.
/// </summary>
internal USHORT ButtonData;// { get { return (USHORT)((Buttons & 0xFFFF0000) >> 16); } }
/// <summary>
/// Raw state of the mouse buttons.
/// </summary>
internal ULONG RawButtons;
/// <summary>
/// Motion in the X direction. This is signed relative motion or absolute motion, depending on the value of usFlags.
/// </summary>
internal LONG LastX;
/// <summary>
/// Motion in the Y direction. This is signed relative motion or absolute motion, depending on the value of usFlags.
/// </summary>
internal LONG LastY;
/// <summary>
/// Device-specific additional information for the event.
/// </summary>
internal ULONG ExtraInformation;
/// <summary>
/// Mouse state. This member can be any reasonable combination of the following.
/// MOUSE_ATTRIBUTES_CHANGED
@ -2384,12 +2354,34 @@ namespace OpenTK.Platform.Windows
/// MOUSE_VIRTUAL_DESKTOP
/// Mouse coordinates are mapped to the virtual desktop (for a multiple monitor system).
/// </summary>
internal RawMouseFlags Flags { get { return (RawMouseFlags)(flags); } }
[FieldOffset(0)] public RawMouseFlags Flags; // USHORT in winuser.h, but only INT works -- USHORT returns 0.
[FieldOffset(4)] public RawInputMouseState ButtonFlags;
/// <summary>
/// Transition state of the mouse buttons.
/// If usButtonFlags is RI_MOUSE_WHEEL, this member is a signed value that specifies the wheel delta.
/// </summary>
internal RawInputMouseState ButtonFlags { get { return (RawInputMouseState)(buttonFlags); } }
[FieldOffset(6)] public USHORT ButtonData;
/// <summary>
/// Raw state of the mouse buttons.
/// </summary>
[FieldOffset(8)] public ULONG RawButtons;
/// <summary>
/// Motion in the X direction. This is signed relative motion or absolute motion, depending on the value of usFlags.
/// </summary>
[FieldOffset(12)] public LONG LastX;
/// <summary>
/// Motion in the Y direction. This is signed relative motion or absolute motion, depending on the value of usFlags.
/// </summary>
[FieldOffset(16)] public LONG LastY;
/// <summary>
/// Device-specific additional information for the event.
/// </summary>
[FieldOffset(20)] public ULONG ExtraInformation;
}
#endregion
@ -2474,10 +2466,11 @@ namespace OpenTK.Platform.Windows
/// Number of HID inputs in bRawData.
/// </summary>
internal DWORD Count;
/// <summary>
/// Raw input data as an array of bytes.
/// </summary>
internal BYTE RawData;
// The RawData field must be marshalled manually.
///// <summary>
///// Raw input data as an array of bytes.
///// </summary>
//internal IntPtr RawData;
}
#endregion
@ -2812,6 +2805,30 @@ namespace OpenTK.Platform.Windows
#endregion
#region BroadcastHeader
struct BroadcastHeader
{
public DWORD Size;
public DeviceBroadcastType DeviceType;
DWORD dbch_reserved;
}
#endregion
#region BroadcastDeviceInterface
struct BroadcastDeviceInterface
{
public DWORD Size;
public DeviceBroadcastType DeviceType;
DWORD dbcc_reserved;
public Guid ClassGuid;
public char dbcc_name;
}
#endregion
#endregion
#region --- Enums ---
@ -3230,6 +3247,7 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Mouse indicator flags (found in winuser.h).
/// </summary>
[Flags]
internal enum RawMouseFlags : ushort
{
/// <summary>
@ -4147,6 +4165,30 @@ namespace OpenTK.Platform.Windows
#endregion
#region DeviceNotification
enum DeviceNotification
{
WINDOW_HANDLE = 0x00000000,
SERVICE_HANDLE = 0x00000001,
ALL_INTERFACE_CLASSES = 0x00000004,
}
#endregion
#region DeviceBroadcastType
enum DeviceBroadcastType
{
OEM = 0,
VOLUME = 2,
PORT = 3,
INTERFACE = 5,
HANDLE = 6,
}
#endregion
#endregion
#region --- Callbacks ---
@ -4207,4 +4249,4 @@ namespace OpenTK.Platform.Windows
#pragma warning restore 3019
#pragma warning restore 0649
#pragma warning restore 0169
#pragma warning restore 0414
#pragma warning restore 0414

View file

@ -1,297 +1,175 @@
#region --- License ---
/* Copyright (c) 2007 Stefanos Apostolopoulos
* See license.txt for license information
*/
#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.Text;
using System.Windows.Forms;
using OpenTK.Input;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Text;
using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
// Input driver for legacy (pre XP) Windows platforms.
sealed class WMInput : System.Windows.Forms.NativeWindow, IInputDriver
// Supports a single mouse and keyboard through async input.
// Supports multiple joysticks through WinMM.
sealed class WMInput : IInputDriver2, IMouseDriver2, IKeyboardDriver2, IGamePadDriver
{
#region --- Fields ---
#region Fields
WinMMJoystick joystick_driver = new WinMMJoystick();
// Driver supports only one keyboard and mouse;
KeyboardDevice keyboard = new KeyboardDevice();
MouseDevice mouse = new MouseDevice();
IList<KeyboardDevice> keyboards = new List<KeyboardDevice>(1);
IList<MouseDevice> mice = new List<MouseDevice>(1);
internal static readonly WinKeyMap KeyMap = new WinKeyMap();
// Used to distinguish left and right control, alt and enter keys.
const long ExtendedBit = 1 << 24;
// Used to distinguish left and right shift keys.
static readonly uint ShiftRightScanCode = Functions.MapVirtualKey(VirtualKeys.RSHIFT, 0);
readonly object MouseLock = new object();
readonly object KeyboardLock = new object();
readonly WinMMJoystick gamepad_driver = new WinMMJoystick();
KeyboardState keyboard = new KeyboardState();
MouseState mouse = new MouseState();
readonly WinKeyMap KeyMap = new WinKeyMap();
#endregion
#region --- Constructor ---
#region Constructor
public WMInput(WinWindowInfo parent)
public WMInput()
: base()
{
Debug.WriteLine("Initalizing WMInput driver.");
Debug.Indent();
AssignHandle(parent.WindowHandle);
Debug.Print("Input window attached to parent {0}", parent);
Debug.Unindent();
keyboard.Description = "Standard Windows keyboard";
keyboard.NumberOfFunctionKeys = 12;
keyboard.NumberOfKeys = 101;
keyboard.NumberOfLeds = 3;
mouse.Description = "Standard Windows mouse";
mouse.NumberOfButtons = 3;
mouse.NumberOfWheels = 1;
keyboards.Add(keyboard);
mice.Add(mouse);
Debug.WriteLine("Using WMInput.");
}
#endregion
#region protected override void WndProc(ref Message msg)
#region Private Members
bool mouse_about_to_enter = false;
protected override void WndProc(ref Message msg)
void UpdateKeyboard()
{
UIntPtr lparam, wparam;
unsafe
for (int i = 0; i < 256; i++)
{
lparam = (UIntPtr)(void*)msg.LParam;
wparam = (UIntPtr)(void*)msg.WParam;
}
switch ((WindowMessage)msg.Msg)
{
// Mouse events:
case WindowMessage.NCMOUSEMOVE:
mouse_about_to_enter = true; // Used to simulate a mouse enter event.
break;
case WindowMessage.MOUSEMOVE:
mouse.Position = new Point(
(int)(lparam.ToUInt32() & 0x0000FFFF),
(int)(lparam.ToUInt32() & 0xFFFF0000) >> 16);
if (mouse_about_to_enter)
{
Cursor.Current = Cursors.Default;
mouse_about_to_enter = false;
}
return;
case WindowMessage.MOUSEWHEEL:
// This is due to inconsistent behavior of the WParam value on 64bit arch, whese
// wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
mouse.Wheel += (int)((long)msg.WParam << 32 >> 48) / 120;
return;
case WindowMessage.LBUTTONDOWN:
mouse[MouseButton.Left] = true;
return;
case WindowMessage.MBUTTONDOWN:
mouse[MouseButton.Middle] = true;
return;
case WindowMessage.RBUTTONDOWN:
mouse[MouseButton.Right] = true;
return;
case WindowMessage.XBUTTONDOWN:
mouse[((wparam.ToUInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
return;
case WindowMessage.LBUTTONUP:
mouse[MouseButton.Left] = false;
return;
case WindowMessage.MBUTTONUP:
mouse[MouseButton.Middle] = false;
return;
case WindowMessage.RBUTTONUP:
mouse[MouseButton.Right] = false;
return;
case WindowMessage.XBUTTONUP:
// TODO: Is this correct?
mouse[((wparam.ToUInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false;
return;
// Keyboard events:
case WindowMessage.KEYDOWN:
case WindowMessage.KEYUP:
case WindowMessage.SYSKEYDOWN:
case WindowMessage.SYSKEYUP:
bool pressed = (WindowMessage)msg.Msg == WindowMessage.KEYDOWN ||
(WindowMessage)msg.Msg == WindowMessage.SYSKEYDOWN;
// Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed
// and released. It looks like neither key is released in this case, or that the wrong key is
// released in the case of Control and Alt.
// To combat this, we are going to release both keys when either is released. Hacky, but should work.
// Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0).
// In this case, both keys will be reported as pressed.
bool extended = (msg.LParam.ToInt64() & ExtendedBit) != 0;
switch ((VirtualKeys)wparam)
{
case VirtualKeys.SHIFT:
// The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit
// to distinguish between left and right keys. Moreover, pressing both keys and releasing one
// may result in both keys being held down (but not always).
// The only reliably way to solve this was reported by BlueMonkMN at the forums: we should
// check the scancodes. It looks like GLFW does the same thing, so it should be reliable.
// TODO: Not 100% reliable, when both keys are pressed at once.
if (ShiftRightScanCode != 0)
{
unchecked
{
if (((lparam.ToUInt32() >> 16) & 0xFF) == ShiftRightScanCode)
keyboard[Input.Key.ShiftRight] = pressed;
else
keyboard[Input.Key.ShiftLeft] = pressed;
}
}
else
{
// Should only fall here on Windows 9x and NT4.0-
keyboard[Input.Key.ShiftLeft] = pressed;
}
return;
case VirtualKeys.CONTROL:
if (extended)
keyboard[Input.Key.ControlRight] = pressed;
else
keyboard[Input.Key.ControlLeft] = pressed;
return;
case VirtualKeys.MENU:
if (extended)
keyboard[Input.Key.AltRight] = pressed;
else
keyboard[Input.Key.AltLeft] = pressed;
return;
case VirtualKeys.RETURN:
if (extended)
keyboard[Key.KeypadEnter] = pressed;
else
keyboard[Key.Enter] = pressed;
return;
default:
if (!WMInput.KeyMap.ContainsKey((VirtualKeys)msg.WParam))
{
Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)msg.WParam, (int)msg.WParam);
break;
}
else
{
keyboard[WMInput.KeyMap[(VirtualKeys)msg.WParam]] = pressed;
return;
}
}
break;
case WindowMessage.KILLFOCUS:
keyboard.ClearKeys();
break;
case WindowMessage.DESTROY:
Debug.Print("Input window detached from parent {0}.", Handle);
ReleaseHandle();
break;
case WindowMessage.QUIT:
Debug.WriteLine("Input window quit.");
this.Dispose();
break;
}
base.WndProc(ref msg);
}
#endregion
#region --- IInputDriver Members ---
#region IInputDriver Members
public void Poll()
{
joystick_driver.Poll();
}
#endregion
#region IKeyboardDriver Members
public IList<KeyboardDevice> Keyboard
{
get { return keyboards; }
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
{
get { return mice; }
}
#endregion
#region IJoystickDriver Members
public IList<JoystickDevice> Joysticks
{
get { return joystick_driver.Joysticks; }
}
#endregion
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
this.ReleaseHandle();
disposed = true;
VirtualKeys key = (VirtualKeys)i;
bool pressed = (Functions.GetAsyncKeyState(key) >> 8) != 0;
if (KeyMap.ContainsKey(key))
{
keyboard[KeyMap[key]] = pressed;
}
}
}
~WMInput()
void UpdateMouse()
{
Dispose(false);
POINT p = new POINT();
Functions.GetCursorPos(ref p);
mouse.X = p.X;
mouse.Y = p.Y;
// Note: we cannot poll the mouse wheel
mouse[MouseButton.Left] = (Functions.GetAsyncKeyState(VirtualKeys.LBUTTON) >> 8) != 0;
mouse[MouseButton.Middle] = (Functions.GetAsyncKeyState(VirtualKeys.RBUTTON) >> 8) != 0;
mouse[MouseButton.Right] = (Functions.GetAsyncKeyState(VirtualKeys.MBUTTON) >> 8) != 0;
mouse[MouseButton.Button1] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON1) >> 8) != 0;
mouse[MouseButton.Button2] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON2) >> 8) != 0;
}
#endregion
#region IInputDriver2 Members
public IKeyboardDriver2 KeyboardDriver
{
get { return this; }
}
public IMouseDriver2 MouseDriver
{
get { return this; }
}
public IGamePadDriver GamePadDriver
{
get { return this; }
}
#endregion
#region IMouseDriver2 Members
public MouseState GetState()
{
lock (MouseLock)
{
UpdateMouse();
return mouse;
}
}
public MouseState GetState(int index)
{
lock (MouseLock)
{
UpdateMouse();
if (index == 0)
return mouse;
else
return new MouseState();
}
}
public void SetPosition(double x, double y)
{
Functions.SetCursorPos((int)x, (int)y);
}
#endregion
#region IKeyboardDriver2 Members
KeyboardState IKeyboardDriver2.GetState()
{
lock (KeyboardLock)
{
UpdateKeyboard();
return keyboard;
}
}
KeyboardState IKeyboardDriver2.GetState(int index)
{
lock (KeyboardLock)
{
UpdateKeyboard();
if (index == 0)
return keyboard;
else
return new KeyboardState();
}
}
string IKeyboardDriver2.GetDeviceName(int index)
{
return "Default Windows Keyboard";
}
#endregion

View file

@ -24,9 +24,9 @@ namespace OpenTK.Platform.Windows
delegatesClass = wglClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
importsClass = wglClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic);
// Ensure core entry points are ready prior to accessing any method.
// Resolves bug [#993]: "Possible bug in GraphicsContext.CreateDummyContext()"
LoadAll();
//// Ensure core entry points are ready prior to accessing any method.
//// Resolves bug [#993]: "Possible bug in GraphicsContext.CreateDummyContext()"
//LoadAll();
}
#endregion
@ -42,6 +42,8 @@ namespace OpenTK.Platform.Windows
private static bool rebuildExtensionList = true;
static readonly object SyncRoot = new object();
#endregion
#region static Delegate LoadDelegate(string name, Type signature)
@ -108,7 +110,10 @@ namespace OpenTK.Platform.Windows
/// </summary>
public static void LoadAll()
{
OpenTK.Platform.Utilities.LoadExtensions(typeof(Wgl));
lock (SyncRoot)
{
OpenTK.Platform.Utilities.LoadExtensions(typeof(Wgl));
}
}
#endregion

View file

@ -1,37 +1,101 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK team.
* This notice may not be removed.
* See license.txt for licensing detailed licensing details.
*/
#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.Text;
using OpenTK.Graphics;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace OpenTK.Platform.Windows
{
internal class WinDisplayDeviceDriver : IDisplayDeviceDriver
sealed class WinDisplayDeviceDriver : DisplayDeviceBase
{
static object display_lock = new object();
static Dictionary<DisplayDevice, string> available_device_names =
new Dictionary<DisplayDevice, string>(); // Needed for ChangeDisplaySettingsEx
readonly object display_lock = new object();
#region --- Constructors ---
#region Constructors
/// <summary>Queries available display devices and display resolutions.</summary>
static WinDisplayDeviceDriver()
public WinDisplayDeviceDriver()
{
RefreshDisplayDevices();
Microsoft.Win32.SystemEvents.DisplaySettingsChanged +=
HandleDisplaySettingsChanged;
}
#endregion
#region IDisplayDeviceDriver Members
#region TryChangeResolution
public sealed override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
{
DeviceMode mode = null;
if (resolution != null)
{
mode = new DeviceMode();
mode.PelsWidth = resolution.Width;
mode.PelsHeight = resolution.Height;
mode.BitsPerPel = resolution.BitsPerPixel;
mode.DisplayFrequency = (int)resolution.RefreshRate;
mode.Fields = Constants.DM_BITSPERPEL
| Constants.DM_PELSWIDTH
| Constants.DM_PELSHEIGHT
| Constants.DM_DISPLAYFREQUENCY;
}
return Constants.DISP_CHANGE_SUCCESSFUL ==
Functions.ChangeDisplaySettingsEx((string)device.Id, mode, IntPtr.Zero,
ChangeDisplaySettingsEnum.Fullscreen, IntPtr.Zero);
}
#endregion
#region TryRestoreResolution
public sealed override bool TryRestoreResolution(DisplayDevice device)
{
return TryChangeResolution(device, null);
}
#endregion
#endregion
#region Private Members
#region RefreshDisplayDevices
public void RefreshDisplayDevices()
{
lock (display_lock)
{
// To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
// we only allow settings to be set through its constructor.
// Thus, we save all necessary parameters in temporary variables
AvailableDevices.Clear();
// We save all necessary parameters in temporary variables
// and construct the device when every needed detail is available.
// The main DisplayDevice constructor adds the newly constructed device
// to the list of available devices.
@ -82,56 +146,37 @@ namespace OpenTK.Platform.Windows
opentk_dev_current_res,
opentk_dev_primary,
opentk_dev_available_res,
opentk_dev_current_res.Bounds);
opentk_dev_current_res.Bounds,
dev1.DeviceName);
available_device_names.Add(opentk_dev, dev1.DeviceName);
AvailableDevices.Add(opentk_dev);
if (opentk_dev_primary)
Primary = opentk_dev;
Debug.Print("DisplayDevice {0} ({1}) supports {2} resolutions.",
device_count, opentk_dev.IsPrimary ? "primary" : "secondary", opentk_dev.AvailableResolutions.Count);
}
}
}
public WinDisplayDeviceDriver()
#endregion
#region HandleDisplaySettingsChanged
void HandleDisplaySettingsChanged(object sender, EventArgs e)
{
RefreshDisplayDevices();
}
#endregion
#region --- IDisplayDeviceDriver Members ---
#region public bool TryChangeResolution(OpenTK.Graphics.DisplayDevice device, DisplayResolution resolution)
public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
~WinDisplayDeviceDriver()
{
DeviceMode mode = null;
if (resolution != null)
{
mode = new DeviceMode();
mode.PelsWidth = resolution.Width;
mode.PelsHeight = resolution.Height;
mode.BitsPerPel = resolution.BitsPerPixel;
mode.DisplayFrequency = (int)resolution.RefreshRate;
mode.Fields = Constants.DM_BITSPERPEL
| Constants.DM_PELSWIDTH
| Constants.DM_PELSHEIGHT
| Constants.DM_DISPLAYFREQUENCY;
}
return Constants.DISP_CHANGE_SUCCESSFUL ==
Functions.ChangeDisplaySettingsEx(available_device_names[device], mode, IntPtr.Zero,
ChangeDisplaySettingsEnum.Fullscreen, IntPtr.Zero);
Microsoft.Win32.SystemEvents.DisplaySettingsChanged -=
HandleDisplaySettingsChanged;
}
#endregion
#region public TryRestoreResolution TryRestoreResolution(OpenTK.Graphics.DisplayDevice device)
public bool TryRestoreResolution(DisplayDevice device)
{
return TryChangeResolution(device, null);
}
#endregion
#endregion
}
}

View file

@ -36,6 +36,9 @@ namespace OpenTK.Platform.Windows
class WinFactory : IPlatformFactory
{
readonly object SyncRoot = new object();
IInputDriver2 inputDriver;
#region IPlatformFactory Members
public virtual INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
@ -71,16 +74,37 @@ namespace OpenTK.Platform.Windows
return new WinGraphicsMode();
}
public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
throw new NotImplementedException();
// If Windows version is NT5 or higher, we are able to use raw input.
if (System.Environment.OSVersion.Version.Major >= 5)
return new WinRawKeyboard();
else
return new WMInput(null);
return InputDriver.KeyboardDriver;
}
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
return InputDriver.MouseDriver;
}
#endregion
IInputDriver2 InputDriver
{
get
{
lock (SyncRoot)
{
if (inputDriver == null)
{
// If Windows version is NT5 or higher, we are able to use raw input.
if (System.Environment.OSVersion.Version.Major > 5 ||
(System.Environment.OSVersion.Version.Major == 5 &&
System.Environment.OSVersion.Version.Minor > 0))
inputDriver = new WinRawInput();
else
inputDriver = new WMInput();
}
return inputDriver;
}
}
}
}
}

View file

@ -27,7 +27,8 @@ namespace OpenTK.Platform.Windows
/// </summary>
internal sealed class WinGLContext : DesktopGraphicsContext
{
static object SyncRoot = new object();
static readonly object LoadLock = new object();
static readonly object SyncRoot = new object();
static IntPtr opengl32Handle;
static bool wgl_loaded;
@ -39,18 +40,7 @@ namespace OpenTK.Platform.Windows
static WinGLContext()
{
lock (SyncRoot)
{
// Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl.
if (opengl32Handle == IntPtr.Zero)
{
opengl32Handle = Functions.LoadLibrary(opengl32Name);
if (opengl32Handle == IntPtr.Zero)
throw new ApplicationException(String.Format("LoadLibrary(\"{0}\") call failed with code {1}",
opengl32Name, Marshal.GetLastWin32Error()));
Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle));
}
}
Init();
}
public WinGLContext(GraphicsMode format, WinWindowInfo window, IGraphicsContext sharedContext,
@ -68,60 +58,60 @@ namespace OpenTK.Platform.Windows
Mode = format;
Debug.Print("OpenGL will be bound to handle: {0}", window.WindowHandle);
Debug.Write("Setting pixel format... ");
Debug.Print("OpenGL will be bound to window:{0} on thread:{1}", window.WindowHandle,
System.Threading.Thread.CurrentThread.ManagedThreadId);
this.SetGraphicsModePFD(format, (WinWindowInfo)window);
if (!wgl_loaded)
lock (LoadLock)
{
// We need to create a temp context in order to load wgl extensions (e.g. for multisampling or GL3).
// We cannot rely on OpenTK.Platform.Wgl until we create the context and call Wgl.LoadAll().
Debug.Print("Creating temporary context for wgl extensions.");
ContextHandle temp_context = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
Wgl.Imports.MakeCurrent(window.DeviceContext, temp_context.Handle);
Wgl.LoadAll();
Wgl.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
Wgl.DeleteContext(temp_context.Handle);
wgl_loaded = true;
}
if (Wgl.Delegates.wglCreateContextAttribsARB != null)
{
try
if (!wgl_loaded)
{
Debug.Write("Using WGL_ARB_create_context... ");
List<int> attributes = new List<int>();
attributes.Add((int)ArbCreateContext.MajorVersion);
attributes.Add(major);
attributes.Add((int)ArbCreateContext.MinorVersion);
attributes.Add(minor);
if (flags != 0)
{
attributes.Add((int)ArbCreateContext.Flags);
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
attributes.Add((int)flags);
}
// According to the docs, " <attribList> specifies a list of attributes for the context.
// The list consists of a sequence of <name,value> pairs terminated by the
// value 0. [...]"
// Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case).
attributes.Add(0);
attributes.Add(0);
Handle = new ContextHandle(
Wgl.Arb.CreateContextAttribs(
window.DeviceContext,
sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero,
attributes.ToArray()));
if (Handle == ContextHandle.Zero)
Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error());
else
Debug.Print("success!");
// We need to create a temp context in order to load wgl extensions (e.g. for multisampling or GL3).
// We cannot rely on OpenTK.Platform.Wgl until we create the context and call Wgl.LoadAll().
Debug.Print("Creating temporary context for wgl extensions.");
ContextHandle temp_context = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
Wgl.Imports.MakeCurrent(window.DeviceContext, temp_context.Handle);
Wgl.LoadAll();
Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
Wgl.Imports.DeleteContext(temp_context.Handle);
wgl_loaded = true;
}
if (Wgl.Delegates.wglCreateContextAttribsARB != null)
{
try
{
Debug.Write("Using WGL_ARB_create_context... ");
List<int> attributes = new List<int>();
attributes.Add((int)ArbCreateContext.MajorVersion);
attributes.Add(major);
attributes.Add((int)ArbCreateContext.MinorVersion);
attributes.Add(minor);
if (flags != 0)
{
attributes.Add((int)ArbCreateContext.Flags);
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
attributes.Add((int)flags);
}
// According to the docs, " <attribList> specifies a list of attributes for the context.
// The list consists of a sequence of <name,value> pairs terminated by the
// value 0. [...]"
// Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case).
attributes.Add(0);
attributes.Add(0);
Handle = new ContextHandle(
Wgl.Arb.CreateContextAttribs(
window.DeviceContext,
sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero,
attributes.ToArray()));
if (Handle == ContextHandle.Zero)
Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error());
}
catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); }
catch (NullReferenceException e) { Debug.Print(e.ToString()); }
}
catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); }
catch (NullReferenceException e) { Debug.Print(e.ToString()); }
}
if (Handle == ContextHandle.Zero)
@ -142,7 +132,7 @@ namespace OpenTK.Platform.Windows
if (sharedContext != null)
{
Marshal.GetLastWin32Error();
Debug.Write("Sharing state with context {0}: ", sharedContext.ToString());
Debug.Write(String.Format("Sharing state with context {0}: ", sharedContext));
bool result = Wgl.Imports.ShareLists((sharedContext as IGraphicsContextInternal).Context.Handle, Handle.Handle);
Debug.WriteLine(result ? "success!" : "failed with win32 error " + Marshal.GetLastWin32Error());
}
@ -162,13 +152,13 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- IGraphicsContext Members ---
#region IGraphicsContext Members
#region SwapBuffers
public override void SwapBuffers()
{
if (!Functions.SwapBuffers(Wgl.GetCurrentDC()))
if (!Functions.SwapBuffers(DeviceContext))
throw new GraphicsContextException(String.Format(
"Failed to swap buffers for context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
}
@ -179,30 +169,36 @@ namespace OpenTK.Platform.Windows
public override void MakeCurrent(IWindowInfo window)
{
bool success;
if (window != null)
lock (SyncRoot)
lock (LoadLock)
{
if (((WinWindowInfo)window).WindowHandle == IntPtr.Zero)
throw new ArgumentException("window", "Must point to a valid window.");
bool success;
success = Wgl.Imports.MakeCurrent(((WinWindowInfo)window).DeviceContext, Handle.Handle);
if (window != null)
{
if (((WinWindowInfo)window).WindowHandle == IntPtr.Zero)
throw new ArgumentException("window", "Must point to a valid window.");
success = Wgl.Imports.MakeCurrent(((WinWindowInfo)window).DeviceContext, Handle.Handle);
}
else
{
success = Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
}
if (!success)
throw new GraphicsContextException(String.Format(
"Failed to make context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
}
else
success = Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
if (!success)
throw new GraphicsContextException(String.Format(
"Failed to make context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
}
#endregion
#region IsCurrent
public override bool IsCurrent
{
get { return Wgl.GetCurrentContext() == Handle.Handle; }
get { return Wgl.Imports.GetCurrentContext() == Handle.Handle; }
}
#endregion
@ -216,12 +212,18 @@ namespace OpenTK.Platform.Windows
{
get
{
return vsync_supported && Wgl.Ext.GetSwapInterval() != 0;
lock (LoadLock)
{
return vsync_supported && Wgl.Ext.GetSwapInterval() != 0;
}
}
set
{
if (vsync_supported)
Wgl.Ext.SwapInterval(value ? 1 : 0);
lock (LoadLock)
{
if (vsync_supported)
Wgl.Ext.SwapInterval(value ? 1 : 0);
}
}
}
@ -231,9 +233,12 @@ namespace OpenTK.Platform.Windows
public override void LoadAll()
{
Wgl.LoadAll();
vsync_supported = Wgl.Arb.SupportsExtension(this, "WGL_EXT_swap_control") &&
Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
lock (LoadLock)
{
Wgl.LoadAll();
vsync_supported = Wgl.Arb.SupportsExtension(this, "WGL_EXT_swap_control") &&
Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
}
base.LoadAll();
}
@ -242,7 +247,7 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- IGLContextInternal Members ---
#region IGLContextInternal Members
#region IWindowInfo IGLContextInternal.Info
/*
@ -264,12 +269,15 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- Private Methods ---
#region Private Methods
#region void SetGraphicsModePFD(GraphicsMode format, WinWindowInfo window)
#region SetGraphicsModePFD
// Note: there is no relevant ARB function.
void SetGraphicsModePFD(GraphicsMode mode, WinWindowInfo window)
{
Debug.Write("Setting pixel format... ");
if (!mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
@ -283,20 +291,12 @@ namespace OpenTK.Platform.Windows
throw new GraphicsContextException(String.Format(
"Requested GraphicsMode not available. SetPixelFormat error: {0}", Marshal.GetLastWin32Error()));
}
#endregion
#region void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window)
void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window)
{
throw new NotImplementedException();
}
#endregion
#endregion
#region --- Internal Methods ---
#region Internal Methods
#region internal IntPtr DeviceContext
@ -304,16 +304,32 @@ namespace OpenTK.Platform.Windows
{
get
{
return Wgl.GetCurrentDC();
return Wgl.Imports.GetCurrentDC();
}
}
#endregion
static internal void Init()
{
lock (SyncRoot)
{
// Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl.
if (opengl32Handle == IntPtr.Zero)
{
opengl32Handle = Functions.LoadLibrary(opengl32Name);
if (opengl32Handle == IntPtr.Zero)
throw new ApplicationException(String.Format("LoadLibrary(\"{0}\") call failed with code {1}",
opengl32Name, Marshal.GetLastWin32Error()));
Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle));
}
}
}
#endregion
#region --- Overrides ---
#region Overrides
/// <summary>Returns a System.String describing this OpenGL context.</summary>
/// <returns>A System.String describing this OpenGL context.</returns>
@ -324,7 +340,7 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- IDisposable Members ---
#region IDisposable Members
public override void Dispose()
{

View file

@ -49,9 +49,11 @@ namespace OpenTK.Platform.Windows
const ExtendedWindowStyle ParentStyleEx = ExtendedWindowStyle.WindowEdge | ExtendedWindowStyle.ApplicationWindow;
const ExtendedWindowStyle ChildStyleEx = 0;
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly IntPtr Instance = Marshal.GetHINSTANCE(typeof(WinGLNative).Module);
readonly IntPtr ClassName = Marshal.StringToHGlobalAuto(Guid.NewGuid().ToString());
readonly WindowProcedure WindowProcedureDelegate;
readonly uint ModalLoopTimerPeriod = 1;
UIntPtr timer_handle;
readonly Functions.TimerProc ModalLoopCallback;
@ -78,59 +80,62 @@ namespace OpenTK.Platform.Windows
const ClassStyle DefaultClassStyle = ClassStyle.OwnDC;
readonly IntPtr DefaultWindowProcedure =
Marshal.GetFunctionPointerForDelegate(new WindowProcedure(Functions.DefWindowProc));
// Used for IInputDriver implementation
WinMMJoystick joystick_driver = new WinMMJoystick();
KeyboardDevice keyboard = new KeyboardDevice();
MouseDevice mouse = new MouseDevice();
IList<KeyboardDevice> keyboards = new List<KeyboardDevice>(1);
IList<MouseDevice> mice = new List<MouseDevice>(1);
internal static readonly WinKeyMap KeyMap = new WinKeyMap();
const long ExtendedBit = 1 << 24; // Used to distinguish left and right control, alt and enter keys.
static readonly uint ShiftRightScanCode = Functions.MapVirtualKey(VirtualKeys.RSHIFT, 0); // Used to distinguish left and right shift keys.
KeyPressEventArgs key_press = new KeyPressEventArgs((char)0);
int cursor_visible_count = 0;
static readonly object SyncRoot = new object();
#endregion
#region Contructors
public WinGLNative(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device)
{
// This is the main window procedure callback. We need the callback in order to create the window, so
// don't move it below the CreateWindow calls.
WindowProcedureDelegate = WindowProcedure;
lock (SyncRoot)
{
// This is the main window procedure callback. We need the callback in order to create the window, so
// don't move it below the CreateWindow calls.
WindowProcedureDelegate = WindowProcedure;
//// This timer callback is called periodically when the window enters a sizing / moving modal loop.
//ModalLoopCallback = delegate(IntPtr handle, WindowMessage msg, UIntPtr eventId, int time)
//{
// // Todo: find a way to notify the frontend that it should process queued up UpdateFrame/RenderFrame events.
// if (Move != null)
// Move(this, EventArgs.Empty);
//};
//// This timer callback is called periodically when the window enters a sizing / moving modal loop.
//ModalLoopCallback = delegate(IntPtr handle, WindowMessage msg, UIntPtr eventId, int time)
//{
// // Todo: find a way to notify the frontend that it should process queued up UpdateFrame/RenderFrame events.
// if (Move != null)
// Move(this, EventArgs.Empty);
//};
// To avoid issues with Ati drivers on Windows 6+ with compositing enabled, the context will not be
// bound to the top-level window, but rather to a child window docked in the parent.
window = new WinWindowInfo(
CreateWindow(x, y, width, height, title, options, device, IntPtr.Zero), null);
child_window = new WinWindowInfo(
CreateWindow(0, 0, ClientSize.Width, ClientSize.Height, title, options, device, window.WindowHandle), window);
// To avoid issues with Ati drivers on Windows 6+ with compositing enabled, the context will not be
// bound to the top-level window, but rather to a child window docked in the parent.
window = new WinWindowInfo(
CreateWindow(x, y, width, height, title, options, device, IntPtr.Zero), null);
child_window = new WinWindowInfo(
CreateWindow(0, 0, ClientSize.Width, ClientSize.Height, title, options, device, window.WindowHandle), window);
exists = true;
exists = true;
keyboard.Description = "Standard Windows keyboard";
keyboard.NumberOfFunctionKeys = 12;
keyboard.NumberOfKeys = 101;
keyboard.NumberOfLeds = 3;
keyboard.Description = "Standard Windows keyboard";
keyboard.NumberOfFunctionKeys = 12;
keyboard.NumberOfKeys = 101;
keyboard.NumberOfLeds = 3;
mouse.Description = "Standard Windows mouse";
mouse.NumberOfButtons = 3;
mouse.NumberOfWheels = 1;
mouse.Description = "Standard Windows mouse";
mouse.NumberOfButtons = 3;
mouse.NumberOfWheels = 1;
keyboards.Add(keyboard);
mice.Add(mouse);
keyboards.Add(keyboard);
mice.Add(mouse);
}
}
#endregion
@ -154,7 +159,7 @@ namespace OpenTK.Platform.Windows
else
focused = (wParam.ToInt64() & 0xFFFF) != 0;
if (new_focused_state != Focused && FocusedChanged != null)
if (new_focused_state != Focused)
FocusedChanged(this, EventArgs.Empty);
break;
@ -186,8 +191,7 @@ namespace OpenTK.Platform.Windows
if (Location != new_location)
{
bounds.Location = new_location;
if (Move != null)
Move(this, EventArgs.Empty);
Move(this, EventArgs.Empty);
}
Size new_size = new Size(pos->cx, pos->cy);
@ -204,9 +208,13 @@ namespace OpenTK.Platform.Windows
SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER |
SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING);
if (suppress_resize <= 0 && Resize != null)
if (suppress_resize <= 0)
Resize(this, EventArgs.Empty);
}
// Ensure cursor remains grabbed
if (!CursorVisible)
GrabCursor();
}
}
break;
@ -226,6 +234,10 @@ namespace OpenTK.Platform.Windows
}
}
// Ensure cursor remains grabbed
if (!CursorVisible)
GrabCursor();
break;
case WindowMessage.SIZE:
@ -244,10 +256,13 @@ namespace OpenTK.Platform.Windows
if (new_state != windowState)
{
windowState = new_state;
if (WindowStateChanged != null)
WindowStateChanged(this, EventArgs.Empty);
WindowStateChanged(this, EventArgs.Empty);
}
// Ensure cursor remains grabbed
if (!CursorVisible)
GrabCursor();
break;
#endregion
@ -260,8 +275,7 @@ namespace OpenTK.Platform.Windows
else
key_press.KeyChar = (char)wParam.ToInt64();
if (KeyPress != null)
KeyPress(this, key_press);
KeyPress(this, key_press);
break;
case WindowMessage.MOUSEMOVE:
@ -277,8 +291,7 @@ namespace OpenTK.Platform.Windows
mouse_outside_window = false;
EnableMouseTracking();
if (MouseEnter != null)
MouseEnter(this, EventArgs.Empty);
MouseEnter(this, EventArgs.Empty);
}
break;
@ -286,8 +299,7 @@ namespace OpenTK.Platform.Windows
mouse_outside_window = true;
// Mouse tracking is disabled automatically by the OS
if (MouseLeave != null)
MouseLeave(this, EventArgs.Empty);
MouseLeave(this, EventArgs.Empty);
break;
case WindowMessage.MOUSEWHEEL:
@ -297,36 +309,45 @@ namespace OpenTK.Platform.Windows
break;
case WindowMessage.LBUTTONDOWN:
Functions.SetCapture(window.WindowHandle);
mouse[MouseButton.Left] = true;
break;
case WindowMessage.MBUTTONDOWN:
Functions.SetCapture(window.WindowHandle);
mouse[MouseButton.Middle] = true;
break;
case WindowMessage.RBUTTONDOWN:
Functions.SetCapture(window.WindowHandle);
mouse[MouseButton.Right] = true;
break;
case WindowMessage.XBUTTONDOWN:
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
Functions.SetCapture(window.WindowHandle);
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) !=
(int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
break;
case WindowMessage.LBUTTONUP:
Functions.ReleaseCapture();
mouse[MouseButton.Left] = false;
break;
case WindowMessage.MBUTTONUP:
Functions.ReleaseCapture();
mouse[MouseButton.Middle] = false;
break;
case WindowMessage.RBUTTONUP:
Functions.ReleaseCapture();
mouse[MouseButton.Right] = false;
break;
case WindowMessage.XBUTTONUP:
// TODO: Is this correct?
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false;
Functions.ReleaseCapture();
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) !=
(int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false;
break;
// Keyboard events:
@ -352,11 +373,12 @@ namespace OpenTK.Platform.Windows
// The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit
// to distinguish between left and right keys. Moreover, pressing both keys and releasing one
// may result in both keys being held down (but not always).
// The only reliably way to solve this was reported by BlueMonkMN at the forums: we should
// The only reliable way to solve this was reported by BlueMonkMN at the forums: we should
// check the scancodes. It looks like GLFW does the same thing, so it should be reliable.
// TODO: Not 100% reliable, when both keys are pressed at once.
if (ShiftRightScanCode != 0)
// Note: we release both keys when either shift is released.
// Otherwise, the state of one key might be stuck to pressed.
if (ShiftRightScanCode != 0 && pressed)
{
unchecked
{
@ -368,8 +390,8 @@ namespace OpenTK.Platform.Windows
}
else
{
// Should only fall here on Windows 9x and NT4.0-
keyboard[Input.Key.ShiftLeft] = pressed;
// Windows 9x and NT4.0 or key release event.
keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed;
}
return IntPtr.Zero;
@ -395,14 +417,14 @@ namespace OpenTK.Platform.Windows
return IntPtr.Zero;
default:
if (!WMInput.KeyMap.ContainsKey((VirtualKeys)wParam))
if (!KeyMap.ContainsKey((VirtualKeys)wParam))
{
Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (int)lParam);
Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam);
break;
}
else
{
keyboard[WMInput.KeyMap[(VirtualKeys)wParam]] = pressed;
keyboard[KeyMap[(VirtualKeys)wParam]] = pressed;
}
return IntPtr.Zero;
}
@ -439,14 +461,10 @@ namespace OpenTK.Platform.Windows
case WindowMessage.CLOSE:
System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs();
if (Closing != null)
Closing(this, e);
Closing(this, e);
if (!e.Cancel)
{
if (Unload != null)
Unload(this, EventArgs.Empty);
DestroyWindow();
break;
}
@ -460,8 +478,7 @@ namespace OpenTK.Platform.Windows
window.Dispose();
child_window.Dispose();
if (Closed != null)
Closed(this, EventArgs.Empty);
Closed(this, EventArgs.Empty);
break;
@ -628,6 +645,24 @@ namespace OpenTK.Platform.Windows
suppress_resize--;
}
void GrabCursor()
{
Win32Rectangle rect = Win32Rectangle.From(ClientRectangle);
Point pos = PointToScreen(new Point(rect.left, rect.top));
rect.left = pos.X;
rect.top = pos.Y;
if (!Functions.ClipCursor(ref rect))
Debug.WriteLine(String.Format("Failed to grab cursor. Error: {0}",
Marshal.GetLastWin32Error()));
}
void UngrabCursor()
{
if (!Functions.ClipCursor(IntPtr.Zero))
Debug.WriteLine(String.Format("Failed to ungrab cursor. Error: {0}",
Marshal.GetLastWin32Error()));
}
#endregion
#region INativeWindow Members
@ -763,11 +798,15 @@ namespace OpenTK.Platform.Windows
}
set
{
icon = value;
if (window.WindowHandle != IntPtr.Zero)
if (value != icon)
{
Functions.SendMessage(window.WindowHandle, WindowMessage.SETICON, (IntPtr)0, icon == null ? IntPtr.Zero : value.Handle);
Functions.SendMessage(window.WindowHandle, WindowMessage.SETICON, (IntPtr)1, icon == null ? IntPtr.Zero : value.Handle);
icon = value;
if (window.WindowHandle != IntPtr.Zero)
{
Functions.SendMessage(window.WindowHandle, WindowMessage.SETICON, (IntPtr)0, icon == null ? IntPtr.Zero : value.Handle);
Functions.SendMessage(window.WindowHandle, WindowMessage.SETICON, (IntPtr)1, icon == null ? IntPtr.Zero : value.Handle);
}
IconChanged(this, EventArgs.Empty);
}
}
}
@ -791,14 +830,18 @@ namespace OpenTK.Platform.Windows
get
{
sb_title.Remove(0, sb_title.Length);
if (Functions.GetWindowText(window.WindowHandle, sb_title, sb_title.MaxCapacity) == 0)
Debug.Print("Failed to retrieve window title (window:{0}, reason:{2}).", window.WindowHandle, Marshal.GetLastWin32Error());
if (Functions.GetWindowText(window.WindowHandle, sb_title, sb_title.Capacity) == 0)
Debug.Print("Failed to retrieve window title (window:{0}, reason:{1}).", window.WindowHandle, Marshal.GetLastWin32Error());
return sb_title.ToString();
}
set
{
if (!Functions.SetWindowText(window.WindowHandle, value))
Debug.Print("Failed to change window title (window:{0}, new title:{1}, reason:{2}).", window.WindowHandle, value, Marshal.GetLastWin32Error());
if (Title != value)
{
if (!Functions.SetWindowText(window.WindowHandle, value))
Debug.Print("Failed to change window title (window:{0}, new title:{1}, reason:{2}).", window.WindowHandle, value, Marshal.GetLastWin32Error());
TitleChanged(this, EventArgs.Empty);
}
}
}
@ -814,18 +857,23 @@ namespace OpenTK.Platform.Windows
}
set
{
if (value)
if (value != Visible)
{
Functions.ShowWindow(window.WindowHandle, ShowWindowCommand.SHOW);
if (invisible_since_creation)
if (value)
{
Functions.BringWindowToTop(window.WindowHandle);
Functions.SetForegroundWindow(window.WindowHandle);
Functions.ShowWindow(window.WindowHandle, ShowWindowCommand.SHOW);
if (invisible_since_creation)
{
Functions.BringWindowToTop(window.WindowHandle);
Functions.SetForegroundWindow(window.WindowHandle);
}
}
}
else if (!value)
{
Functions.ShowWindow(window.WindowHandle, ShowWindowCommand.HIDE);
else if (!value)
{
Functions.ShowWindow(window.WindowHandle, ShowWindowCommand.HIDE);
}
VisibleChanged(this, EventArgs.Empty);
}
}
}
@ -836,6 +884,38 @@ namespace OpenTK.Platform.Windows
public bool Exists { get { return exists; } }
#endregion
#region CursorVisible
public bool CursorVisible
{
get { return cursor_visible_count >= 0; } // Not used
set
{
if (value && cursor_visible_count < 0)
{
do
{
cursor_visible_count = Functions.ShowCursor(true);
}
while (cursor_visible_count < 0);
UngrabCursor();
}
else if (!value && cursor_visible_count >= 0)
{
do
{
cursor_visible_count = Functions.ShowCursor(false);
}
while (cursor_visible_count >= 0);
GrabCursor();
}
}
}
#endregion
#region Close
@ -1012,8 +1092,7 @@ namespace OpenTK.Platform.Windows
WindowState = state;
if (WindowBorderChanged != null)
WindowBorderChanged(this, EventArgs.Empty);
WindowBorderChanged(this, EventArgs.Empty);
}
}
@ -1025,7 +1104,7 @@ namespace OpenTK.Platform.Windows
{
if (!Functions.ScreenToClient(window.WindowHandle, ref point))
throw new InvalidOperationException(String.Format(
"Could not convert point {0} from client to screen coordinates. Windows error: {1}",
"Could not convert point {0} from screen to client coordinates. Windows error: {1}",
point.ToString(), Marshal.GetLastWin32Error()));
return point;
@ -1035,52 +1114,36 @@ namespace OpenTK.Platform.Windows
#region PointToScreen
public Point PointToScreen(Point p)
public Point PointToScreen(Point point)
{
throw new NotImplementedException();
if (!Functions.ClientToScreen(window.WindowHandle, ref point))
throw new InvalidOperationException(String.Format(
"Could not convert point {0} from screen to client coordinates. Windows error: {1}",
point.ToString(), Marshal.GetLastWin32Error()));
return point;
}
#endregion
#region Events
public event EventHandler<EventArgs> Idle;
public event EventHandler<EventArgs> Load;
public event EventHandler<EventArgs> Unload;
public event EventHandler<EventArgs> Move;
public event EventHandler<EventArgs> Resize;
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing;
public event EventHandler<EventArgs> Closed;
public event EventHandler<EventArgs> Disposed;
public event EventHandler<EventArgs> IconChanged;
public event EventHandler<EventArgs> TitleChanged;
public event EventHandler<EventArgs> ClientSizeChanged;
public event EventHandler<EventArgs> VisibleChanged;
public event EventHandler<EventArgs> WindowInfoChanged;
public event EventHandler<EventArgs> FocusedChanged;
public event EventHandler<EventArgs> WindowBorderChanged;
public event EventHandler<EventArgs> WindowStateChanged;
public event EventHandler<KeyPressEventArgs> KeyPress;
public event EventHandler<EventArgs> MouseEnter;
public event EventHandler<EventArgs> MouseLeave;
public event EventHandler<EventArgs> Move = delegate { };
public event EventHandler<EventArgs> Resize = delegate { };
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
public event EventHandler<EventArgs> Closed = delegate { };
public event EventHandler<EventArgs> Disposed = delegate { };
public event EventHandler<EventArgs> IconChanged = delegate { };
public event EventHandler<EventArgs> TitleChanged = delegate { };
public event EventHandler<EventArgs> VisibleChanged = delegate { };
public event EventHandler<EventArgs> FocusedChanged = delegate { };
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyDown = delegate { };
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyUp = delegate { };
public event EventHandler<EventArgs> MouseEnter = delegate { };
public event EventHandler<EventArgs> MouseLeave = delegate { };
#endregion
@ -1147,6 +1210,16 @@ namespace OpenTK.Platform.Windows
get { return keyboards; }
}
public KeyboardState GetState()
{
throw new NotImplementedException();
}
public KeyboardState GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IMouseDriver Members
@ -1191,6 +1264,7 @@ namespace OpenTK.Platform.Windows
Debug.Print("[Warning] INativeWindow leaked ({0}). Did you forget to call INativeWindow.Dispose()?", this);
}
Disposed(this, EventArgs.Empty);
disposed = true;
}
}

View file

@ -2,7 +2,7 @@
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2009 the Open Toolkit library.
// 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
@ -28,144 +28,158 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using OpenTK.Graphics;
using ColorDepth = OpenTK.Graphics.ColorFormat;
namespace OpenTK.Platform.Windows
{
internal class WinGraphicsMode : IGraphicsMode
class WinGraphicsMode : IGraphicsMode
{
// Todo: Get rid of the System.Windows.Forms.Control dependency.
#region Fields
#region --- Fields ---
// To avoid recursion when calling GraphicsMode.Default
bool creating;
readonly List<GraphicsMode> modes = new List<GraphicsMode>();
static readonly object SyncRoot = new object();
#endregion
#region --- Constructors ---
#region Constructors
public WinGraphicsMode()
{
lock (SyncRoot)
{
using (INativeWindow native = new NativeWindow())
{
modes.AddRange(GetModesARB(native));
if (modes.Count == 0)
modes.AddRange(GetModesPFD(native));
if (modes.Count == 0)
throw new GraphicsModeException(
"No GraphicsMode available. This should never happen, please report a bug at http://www.opentk.com");
}
modes.Sort(new GraphicsModeComparer());
}
}
#endregion
#region --- IGraphicsMode Members ---
#region IGraphicsMode Members
public GraphicsMode SelectGraphicsMode(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum,
int buffers, bool stereo)
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo)
{
GraphicsMode mode = null;
if (!creating)
do
{
try
mode = modes.Find(delegate(GraphicsMode current)
{
creating = true;
mode = SelectGraphicsModeARB(color, depth, stencil, samples, accum, buffers, stereo);
}
finally
{
creating = false;
}
}
return ModeSelector(current, color, depth, stencil, samples, accum, buffers, stereo);
});
} while (mode == null && RelaxParameters(
ref color, ref depth, ref stencil, ref samples, ref accum, ref buffers, ref stereo));
if (mode == null)
mode = SelectGraphicsModePFD(color, depth, stencil, samples, accum, buffers, stereo);
mode = modes[0];
return mode;
}
bool RelaxParameters(ref ColorFormat color, ref int depth, ref int stencil, ref int samples,
ref ColorFormat accum, ref int buffers, ref bool stereo)
{
if (stereo) { stereo = false; return true; }
if (buffers != 2) { buffers = 2; return true; }
if (accum != 0) { accum = 0; return true; }
if (samples != 0) { samples = 0; return true; }
if (depth < 16) { depth = 16; return true; }
if (depth != 24) { depth = 24; return true; }
if (stencil > 0 && stencil != 8) { stencil = 8; return true; }
if (stencil == 8) { stencil = 0; return true; }
if (color < 8) { color = 8; return true; }
if (color < 16) { color = 16; return true; }
if (color < 24) { color = 24; return true; }
if (color < 32 || color > 32) { color = 32; return true; }
return false; // We tried everything we could, no match found.
}
#endregion
#region --- Private Methods ---
#region Private Methods
#region SelectGraphicsModePFD
#region DescribePixelFormat
GraphicsMode SelectGraphicsModePFD(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum,
int buffers, bool stereo)
static int DescribePixelFormat(IntPtr hdc, int ipfd, int cjpfd, ref PixelFormatDescriptor pfd)
{
using (Control native_window = new Control())
using (WinWindowInfo window = new WinWindowInfo(native_window.Handle, null))
unsafe
{
IntPtr deviceContext = ((WinWindowInfo)window).DeviceContext;
Debug.WriteLine(String.Format("Device context: {0}", deviceContext));
Debug.Write("Selecting pixel format... ");
PixelFormatDescriptor pixelFormat = new PixelFormatDescriptor();
pixelFormat.Size = API.PixelFormatDescriptorSize;
pixelFormat.Version = API.PixelFormatDescriptorVersion;
pixelFormat.Flags =
PixelFormatDescriptorFlags.SUPPORT_OPENGL |
PixelFormatDescriptorFlags.DRAW_TO_WINDOW;
pixelFormat.ColorBits = (byte)(color.Red + color.Green + color.Blue);
pixelFormat.PixelType = color.IsIndexed ? PixelType.INDEXED : PixelType.RGBA;
pixelFormat.RedBits = (byte)color.Red;
pixelFormat.GreenBits = (byte)color.Green;
pixelFormat.BlueBits = (byte)color.Blue;
pixelFormat.AlphaBits = (byte)color.Alpha;
if (accum.BitsPerPixel > 0)
fixed (PixelFormatDescriptor* ppfd = &pfd)
{
pixelFormat.AccumBits = (byte)(accum.Red + accum.Green + accum.Blue);
pixelFormat.AccumRedBits = (byte)accum.Red;
pixelFormat.AccumGreenBits = (byte)accum.Green;
pixelFormat.AccumBlueBits = (byte)accum.Blue;
pixelFormat.AccumAlphaBits = (byte)accum.Alpha;
// Note: DescribePixelFormat found in gdi32 is extremely slow
// on nvidia, for some reason.
return Wgl.Imports.DescribePixelFormat(hdc, ipfd, (uint)cjpfd, ppfd);
}
pixelFormat.DepthBits = (byte)depth;
pixelFormat.StencilBits = (byte)stencil;
if (depth <= 0) pixelFormat.Flags |= PixelFormatDescriptorFlags.DEPTH_DONTCARE;
if (stereo) pixelFormat.Flags |= PixelFormatDescriptorFlags.STEREO;
if (buffers > 1) pixelFormat.Flags |= PixelFormatDescriptorFlags.DOUBLEBUFFER;
int pixel = Functions.ChoosePixelFormat(deviceContext, ref pixelFormat);
if (pixel == 0)
throw new GraphicsModeException("The requested GraphicsMode is not available.");
// Find out what we really got as a format:
PixelFormatDescriptor pfd = new PixelFormatDescriptor();
pixelFormat.Size = API.PixelFormatDescriptorSize;
pixelFormat.Version = API.PixelFormatDescriptorVersion;
Functions.DescribePixelFormat(deviceContext, pixel, API.PixelFormatDescriptorSize, ref pfd);
GraphicsMode fmt = new GraphicsMode((IntPtr)pixel,
new ColorDepth(pfd.RedBits, pfd.GreenBits, pfd.BlueBits, pfd.AlphaBits),
pfd.DepthBits,
pfd.StencilBits,
0,
new ColorDepth(pfd.AccumBits),
(pfd.Flags & PixelFormatDescriptorFlags.DOUBLEBUFFER) != 0 ? 2 : 1,
(pfd.Flags & PixelFormatDescriptorFlags.STEREO) != 0);
return fmt;
}
}
#endregion
#region SelectGraphicsModeARB
#region GetModesPFD
GraphicsMode SelectGraphicsModeARB(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum,
int buffers, bool stereo)
IEnumerable<GraphicsMode> GetModesPFD(INativeWindow native)
{
using (INativeWindow native_window = new NativeWindow())
using (IGraphicsContext context = new GraphicsContext(new GraphicsMode(new ColorFormat(), 0, 0, 0, new ColorFormat(), 2, false), native_window.WindowInfo, 1, 0, GraphicsContextFlags.Default))
{
WinWindowInfo window = (WinWindowInfo)native_window.WindowInfo;
WinWindowInfo window = native.WindowInfo as WinWindowInfo;
IntPtr deviceContext = ((WinWindowInfo)window).DeviceContext;
Debug.WriteLine(String.Format("Device context: {0}", deviceContext));
// See http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
Debug.WriteLine("Retrieving PFD pixel formats... ");
PixelFormatDescriptor pfd = new PixelFormatDescriptor();
pfd.Size = API.PixelFormatDescriptorSize;
pfd.Version = API.PixelFormatDescriptorVersion;
pfd.Flags =
PixelFormatDescriptorFlags.SUPPORT_OPENGL |
PixelFormatDescriptorFlags.DRAW_TO_WINDOW;
int pixel = 0;
while (DescribePixelFormat(deviceContext, ++pixel, API.PixelFormatDescriptorSize, ref pfd) != 0)
{
// Ignore non-accelerated formats.
if ((pfd.Flags & PixelFormatDescriptorFlags.GENERIC_FORMAT) != 0)
continue;
GraphicsMode fmt = new GraphicsMode((IntPtr)pixel,
new ColorFormat(pfd.RedBits, pfd.GreenBits, pfd.BlueBits, pfd.AlphaBits),
pfd.DepthBits,
pfd.StencilBits,
0,
new ColorFormat(pfd.AccumBits),
(pfd.Flags & PixelFormatDescriptorFlags.DOUBLEBUFFER) != 0 ? 2 : 1,
(pfd.Flags & PixelFormatDescriptorFlags.STEREO) != 0);
yield return fmt;
}
}
#endregion
#region GetModesARB
IEnumerable<GraphicsMode> GetModesARB(INativeWindow native)
{
using (IGraphicsContext context = new GraphicsContext(
new GraphicsMode(new IntPtr(2), new ColorFormat(), 0, 0, 0, new ColorFormat(), 2, false),
(WinWindowInfo)native.WindowInfo, 1, 0, GraphicsContextFlags.Default))
{
WinWindowInfo window = (WinWindowInfo)native.WindowInfo;
// See http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
// for more details
Debug.Write("Selecting pixel format (ARB)... ");
Debug.Write("Retrieving ARB pixel formats.... ");
if (Wgl.Delegates.wglChoosePixelFormatARB == null || Wgl.Delegates.wglGetPixelFormatAttribivARB == null)
{
Debug.WriteLine("failed");
return null;
Debug.WriteLine("failed.");
yield break;
}
int[] attribs = new int[]
@ -199,74 +213,61 @@ namespace OpenTK.Platform.Windows
int[] attribs_values = new int[]
{
(int)WGL_ARB_pixel_format.AccelerationArb, (int)WGL_ARB_pixel_format.FullAccelerationArb,
(int)WGL_ARB_pixel_format.DrawToWindowArb, 1,
(int)WGL_ARB_pixel_format.RedBitsArb, color.Red,
(int)WGL_ARB_pixel_format.GreenBitsArb, color.Green,
(int)WGL_ARB_pixel_format.BlueBitsArb, color.Blue,
(int)WGL_ARB_pixel_format.AlphaBitsArb, color.Alpha,
(int)WGL_ARB_pixel_format.ColorBitsArb, color.BitsPerPixel - color.Alpha, // Should not contain alpha bpp (see spec)
(int)WGL_ARB_pixel_format.DepthBitsArb, depth,
(int)WGL_ARB_pixel_format.StencilBitsArb, stencil,
(int)WGL_ARB_multisample.SampleBuffersArb, samples > 0 ? 1 : 0,
(int)WGL_ARB_multisample.SamplesArb, samples,
(int)WGL_ARB_pixel_format.AccumRedBitsArb, accum.Red,
(int)WGL_ARB_pixel_format.AccumGreenBitsArb, accum.Green,
(int)WGL_ARB_pixel_format.AccumBlueBitsArb, accum.Blue,
(int)WGL_ARB_pixel_format.AccumAlphaBitsArb, accum.Alpha,
(int)WGL_ARB_pixel_format.AccumBitsArb, accum.BitsPerPixel, // Spec doesn't mention wether alpha bpp should be included...
(int)WGL_ARB_pixel_format.DoubleBufferArb, buffers > 1 ? 1 : 0,
(int)WGL_ARB_pixel_format.StereoArb, stereo ? 1 : 0,
(int)WGL_ARB_pixel_format.AccelerationArb,
(int)WGL_ARB_pixel_format.FullAccelerationArb,
0, 0
};
int[] pixel = new int[1], num_formats = new int[1];
bool success = Wgl.Arb.ChoosePixelFormat(window.DeviceContext, attribs_values, null, 1, pixel, num_formats);
if (!success || num_formats[0] == 0 || pixel[0] == 0)
{
// Try again without an accumulator. Many modern cards cannot accelerate multisampled formats with accumulator buffers.
int index_of_accum = Array.IndexOf(attribs_values, (int)WGL_ARB_pixel_format.AccumRedBitsArb);
attribs_values[index_of_accum + 1] = attribs_values[index_of_accum + 3] =
attribs_values[index_of_accum + 5] = attribs_values[index_of_accum + 7] =
attribs_values[index_of_accum + 9] = 0;
Wgl.Arb.ChoosePixelFormat(window.DeviceContext, attribs_values, null, 1, pixel, num_formats);
}
if (!success || num_formats[0] == 0 || pixel[0] == 0)
{
Debug.WriteLine("failed (no suitable pixel format).");
return null;
}
int[] num_formats = new int[1];
Wgl.Arb.ChoosePixelFormat(window.DeviceContext, attribs_values, null, 0, null, num_formats);
int[] pixel = new int[num_formats[0]];
// Find out what we really got as a format:
success = Wgl.Arb.GetPixelFormatAttrib(window.DeviceContext, pixel[0], 0, attribs.Length - 1, attribs, values);
if (!success)
if (Wgl.Arb.ChoosePixelFormat(window.DeviceContext, attribs_values, null, pixel.Length, pixel, num_formats))
{
Debug.WriteLine("failed (pixel format attributes could not be determined).");
return null;
}
GraphicsMode mode = new GraphicsMode(new IntPtr(pixel[0]),
new ColorDepth(values[1], values[2], values[3], values[4]),
values[6],
values[7],
values[8] != 0 ? values[9] : 0,
new ColorDepth(values[10], values[11], values[12], values[13]),
values[15] == 1 ? 2 : 1,
values[16] == 1 ? true : false);
foreach (int p in pixel)
{
// Find out what we really got as a format:
if (!Wgl.Arb.GetPixelFormatAttrib(window.DeviceContext, p, 0, attribs.Length - 1, attribs, values))
{
Debug.Print("[Warning] Failed to detect attributes for PixelFormat:{0}.", p);
continue;
}
Debug.WriteLine("success!");
return mode;
GraphicsMode mode = new GraphicsMode(new IntPtr(p),
new ColorFormat(values[1], values[2], values[3], values[4]),
values[6],
values[7],
values[8] != 0 ? values[9] : 0,
new ColorFormat(values[10], values[11], values[12], values[13]),
values[15] == 1 ? 2 : 1,
values[16] == 1 ? true : false);
yield return mode;
}
}
}
}
#endregion
#region ModeSelector
bool ModeSelector(GraphicsMode current, ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo)
{
bool result =
(color != ColorFormat.Empty ? current.ColorFormat >= color : true) &&
(depth != 0 ? current.Depth >= depth : true) &&
(stencil != 0 ? current.Stencil >= stencil : true) &&
(samples != 0 ? current.Samples >= samples : true) &&
(accum != ColorFormat.Empty ? current.AccumulatorFormat >= accum : true) &&
(buffers != 0 ? current.Buffers >= buffers : true) &&
current.Stereo == stereo;
return result;
}
#endregion
#endregion
}
}

View file

@ -0,0 +1,203 @@
#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.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
abstract class WinInputBase : IInputDriver2
{
#region Fields
readonly WindowProcedure WndProc;
readonly Thread InputThread;
readonly AutoResetEvent InputReady = new AutoResetEvent(false);
IntPtr OldWndProc;
INativeWindow native;
protected INativeWindow Native { get { return native; } private set { native = value; } }
protected WinWindowInfo Parent { get { return (WinWindowInfo)Native.WindowInfo; } }
static readonly IntPtr Unhandled = new IntPtr(-1);
#endregion
#region Constructors
public WinInputBase()
{
WndProc = WindowProcedure;
InputThread = new Thread(ProcessEvents);
InputThread.IsBackground = true;
InputThread.Start();
InputReady.WaitOne();
}
#endregion
#region Private Members
#region ConstructMessageWindow
INativeWindow ConstructMessageWindow()
{
Debug.WriteLine("Initializing input driver.");
Debug.Indent();
// Create a new message-only window to retrieve WM_INPUT messages.
INativeWindow native = new NativeWindow();
native.ProcessEvents();
WinWindowInfo parent = native.WindowInfo as WinWindowInfo;
Functions.SetParent(parent.WindowHandle, Constants.MESSAGE_ONLY);
native.ProcessEvents();
Debug.Unindent();
return native;
}
#endregion
#region ProcessEvents
void ProcessEvents()
{
Native = ConstructMessageWindow();
CreateDrivers();
// Subclass the window to retrieve the events we are interested in.
OldWndProc = Functions.SetWindowLong(Parent.WindowHandle, WndProc);
Debug.Print("Input window attached to {0}", Parent);
InputReady.Set();
MSG msg = new MSG();
while (Native.Exists)
{
int ret = Functions.GetMessage(ref msg, Parent.WindowHandle, 0, 0);
if (ret == -1)
{
throw new PlatformException(String.Format(
"An error happened while processing the message queue. Windows error: {0}",
Marshal.GetLastWin32Error()));
}
Functions.TranslateMessage(ref msg);
Functions.DispatchMessage(ref msg);
}
}
#endregion
#region WndProcHandler
IntPtr WndProcHandler(
IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
IntPtr ret = WindowProcedure(handle, message, wParam, lParam);
if (ret == Unhandled)
return Functions.CallWindowProc(OldWndProc, handle, message, wParam, lParam);
else
return ret;
}
#endregion
#endregion
#region Protected Members
#region WindowProcedure
protected virtual IntPtr WindowProcedure(
IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
return Unhandled;
}
#endregion
#region CreateDrivers
// Note: this method is called through the input thread.
protected abstract void CreateDrivers();
#endregion
#endregion
#region IInputDriver2 Members
public abstract IMouseDriver2 MouseDriver { get; }
public abstract IKeyboardDriver2 KeyboardDriver { get; }
public abstract IGamePadDriver GamePadDriver { get; }
#endregion
#region IDisposable Members
protected bool Disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool manual)
{
if (!Disposed)
{
if (manual)
{
if (Native != null)
{
Native.Close();
Native.Dispose();
}
}
Disposed = true;
}
}
~WinInputBase()
{
Debug.Print("[Warning] Resource leaked: {0}.", this);
Dispose(false);
}
#endregion
}
}

View file

@ -1,113 +1,122 @@
#region --- License ---
/* Copyright (c) 2007 Stefanos Apostolopoulos
* See license.txt for license information
*/
#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.Text;
using OpenTK.Platform.Windows;
using OpenTK.Input;
using System.Diagnostics;
namespace OpenTK.Platform.Windows
{
internal class WinKeyMap : Dictionary<VirtualKeys, Input.Key>
class WinKeyMap : Dictionary<VirtualKeys, Input.Key>
{
/// <summary>
/// Initializes the map between VirtualKeys and OpenTK.Key
/// </summary>
internal WinKeyMap()
public WinKeyMap()
{
try
this.Add(VirtualKeys.ESCAPE, Key.Escape);
// Function keys
for (int i = 0; i < 24; i++)
{
this.Add(VirtualKeys.ESCAPE, Key.Escape);
// Function keys
for (int i = 0; i < 24; i++)
{
this.Add((VirtualKeys)((int)VirtualKeys.F1 + i), Key.F1 + i);
}
// Number keys (0-9)
for (int i = 0; i <= 9; i++)
{
this.Add((VirtualKeys)(0x30 + i), Key.Number0 + i);
}
// Letters (A-Z)
for (int i = 0; i < 26; i++)
{
this.Add((VirtualKeys)(0x41 + i), Key.A + i);
}
this.Add(VirtualKeys.TAB, Key.Tab);
this.Add(VirtualKeys.CAPITAL, Key.CapsLock);
this.Add(VirtualKeys.LCONTROL, Key.ControlLeft);
this.Add(VirtualKeys.LSHIFT, Key.ShiftLeft);
this.Add(VirtualKeys.LWIN, Key.WinLeft);
this.Add(VirtualKeys.LMENU, Key.AltLeft);
this.Add(VirtualKeys.SPACE, Key.Space);
this.Add(VirtualKeys.RMENU, Key.AltRight);
this.Add(VirtualKeys.RWIN, Key.WinRight);
this.Add(VirtualKeys.APPS, Key.Menu);
this.Add(VirtualKeys.RCONTROL, Key.ControlRight);
this.Add(VirtualKeys.RSHIFT, Key.ShiftRight);
this.Add(VirtualKeys.RETURN, Key.Enter);
this.Add(VirtualKeys.BACK, Key.BackSpace);
this.Add(VirtualKeys.OEM_1, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
this.Add(VirtualKeys.OEM_2, Key.Slash); // Varies by keyboard, /? on Win2K/US
this.Add(VirtualKeys.OEM_3, Key.Tilde); // Varies by keyboard, `~ on Win2K/US
this.Add(VirtualKeys.OEM_4, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US
this.Add(VirtualKeys.OEM_5, Key.BackSlash); // Varies by keyboard, \| on Win2K/US
this.Add(VirtualKeys.OEM_6, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US
this.Add(VirtualKeys.OEM_7, Key.Quote); // Varies by keyboard, '" on Win2K/US
this.Add(VirtualKeys.OEM_PLUS, Key.Plus); // Invariant: +
this.Add(VirtualKeys.OEM_COMMA, Key.Comma); // Invariant: ,
this.Add(VirtualKeys.OEM_MINUS, Key.Minus); // Invariant: -
this.Add(VirtualKeys.OEM_PERIOD, Key.Period); // Invariant: .
this.Add(VirtualKeys.HOME, Key.Home);
this.Add(VirtualKeys.END, Key.End);
this.Add(VirtualKeys.DELETE, Key.Delete);
this.Add(VirtualKeys.PRIOR, Key.PageUp);
this.Add(VirtualKeys.NEXT, Key.PageDown);
this.Add(VirtualKeys.PRINT, Key.PrintScreen);
this.Add(VirtualKeys.PAUSE, Key.Pause);
this.Add(VirtualKeys.NUMLOCK, Key.NumLock);
this.Add(VirtualKeys.SCROLL, Key.ScrollLock);
this.Add(VirtualKeys.SNAPSHOT, Key.PrintScreen);
this.Add(VirtualKeys.CLEAR, Key.Clear);
this.Add(VirtualKeys.INSERT, Key.Insert);
this.Add(VirtualKeys.SLEEP, Key.Sleep);
// Keypad
for (int i = 0; i <= 9; i++)
{
this.Add((VirtualKeys)((int)VirtualKeys.NUMPAD0 + i), Key.Keypad0 + i);
}
this.Add(VirtualKeys.DECIMAL, Key.KeypadDecimal);
this.Add(VirtualKeys.ADD, Key.KeypadAdd);
this.Add(VirtualKeys.SUBTRACT, Key.KeypadSubtract);
this.Add(VirtualKeys.DIVIDE, Key.KeypadDivide);
this.Add(VirtualKeys.MULTIPLY, Key.KeypadMultiply);
// Navigation
this.Add(VirtualKeys.UP, Key.Up);
this.Add(VirtualKeys.DOWN, Key.Down);
this.Add(VirtualKeys.LEFT, Key.Left);
this.Add(VirtualKeys.RIGHT, Key.Right);
this.Add((VirtualKeys)((int)VirtualKeys.F1 + i), Key.F1 + i);
}
catch (ArgumentException e)
// Number keys (0-9)
for (int i = 0; i <= 9; i++)
{
Debug.Print("Exception while creating keymap: '{0}'.", e.ToString());
System.Windows.Forms.MessageBox.Show(
String.Format("Exception while creating keymap: '{0}'.", e.ToString()));
this.Add((VirtualKeys)(0x30 + i), Key.Number0 + i);
}
// Letters (A-Z)
for (int i = 0; i < 26; i++)
{
this.Add((VirtualKeys)(0x41 + i), Key.A + i);
}
this.Add(VirtualKeys.TAB, Key.Tab);
this.Add(VirtualKeys.CAPITAL, Key.CapsLock);
this.Add(VirtualKeys.LCONTROL, Key.ControlLeft);
this.Add(VirtualKeys.LSHIFT, Key.ShiftLeft);
this.Add(VirtualKeys.LWIN, Key.WinLeft);
this.Add(VirtualKeys.LMENU, Key.AltLeft);
this.Add(VirtualKeys.SPACE, Key.Space);
this.Add(VirtualKeys.RMENU, Key.AltRight);
this.Add(VirtualKeys.RWIN, Key.WinRight);
this.Add(VirtualKeys.APPS, Key.Menu);
this.Add(VirtualKeys.RCONTROL, Key.ControlRight);
this.Add(VirtualKeys.RSHIFT, Key.ShiftRight);
this.Add(VirtualKeys.RETURN, Key.Enter);
this.Add(VirtualKeys.BACK, Key.BackSpace);
this.Add(VirtualKeys.OEM_1, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
this.Add(VirtualKeys.OEM_2, Key.Slash); // Varies by keyboard, /? on Win2K/US
this.Add(VirtualKeys.OEM_3, Key.Tilde); // Varies by keyboard, `~ on Win2K/US
this.Add(VirtualKeys.OEM_4, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US
this.Add(VirtualKeys.OEM_5, Key.BackSlash); // Varies by keyboard, \| on Win2K/US
this.Add(VirtualKeys.OEM_6, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US
this.Add(VirtualKeys.OEM_7, Key.Quote); // Varies by keyboard, '" on Win2K/US
this.Add(VirtualKeys.OEM_PLUS, Key.Plus); // Invariant: +
this.Add(VirtualKeys.OEM_COMMA, Key.Comma); // Invariant: ,
this.Add(VirtualKeys.OEM_MINUS, Key.Minus); // Invariant: -
this.Add(VirtualKeys.OEM_PERIOD, Key.Period); // Invariant: .
this.Add(VirtualKeys.HOME, Key.Home);
this.Add(VirtualKeys.END, Key.End);
this.Add(VirtualKeys.DELETE, Key.Delete);
this.Add(VirtualKeys.PRIOR, Key.PageUp);
this.Add(VirtualKeys.NEXT, Key.PageDown);
this.Add(VirtualKeys.PRINT, Key.PrintScreen);
this.Add(VirtualKeys.PAUSE, Key.Pause);
this.Add(VirtualKeys.NUMLOCK, Key.NumLock);
this.Add(VirtualKeys.SCROLL, Key.ScrollLock);
this.Add(VirtualKeys.SNAPSHOT, Key.PrintScreen);
this.Add(VirtualKeys.CLEAR, Key.Clear);
this.Add(VirtualKeys.INSERT, Key.Insert);
this.Add(VirtualKeys.SLEEP, Key.Sleep);
// Keypad
for (int i = 0; i <= 9; i++)
{
this.Add((VirtualKeys)((int)VirtualKeys.NUMPAD0 + i), Key.Keypad0 + i);
}
this.Add(VirtualKeys.DECIMAL, Key.KeypadDecimal);
this.Add(VirtualKeys.ADD, Key.KeypadAdd);
this.Add(VirtualKeys.SUBTRACT, Key.KeypadSubtract);
this.Add(VirtualKeys.DIVIDE, Key.KeypadDivide);
this.Add(VirtualKeys.MULTIPLY, Key.KeypadMultiply);
// Navigation
this.Add(VirtualKeys.UP, Key.Up);
this.Add(VirtualKeys.DOWN, Key.Down);
this.Add(VirtualKeys.LEFT, Key.Left);
this.Add(VirtualKeys.RIGHT, Key.Right);
}
}
}

View file

@ -36,7 +36,7 @@ using System.Diagnostics;
namespace OpenTK.Platform.Windows
{
sealed class WinMMJoystick : IJoystickDriver
sealed class WinMMJoystick : IJoystickDriver, IGamePadDriver
{
#region Fields

View file

@ -1,60 +1,169 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#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
#region --- Using directives ---
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using OpenTK.Input;
#endregion
namespace OpenTK.Platform.Windows
{
// Not complete.
sealed class WinRawInput : System.Windows.Forms.NativeWindow, IInputDriver
sealed class WinRawInput : WinInputBase
{
#region Fields
// Input event data.
RawInput data = new RawInput();
// The total number of input devices connected to this system.
static int deviceCount;
int rawInputStructSize = API.RawInputSize;
static RawInput data = new RawInput();
static readonly int rawInputStructSize = API.RawInputSize;
private WinRawKeyboard keyboardDriver;
private WinRawMouse mouseDriver;
WinRawKeyboard keyboard_driver;
WinRawMouse mouse_driver;
WinMMJoystick joystick_driver;
#region --- Constructors ---
IntPtr DevNotifyHandle;
static readonly Guid DeviceInterfaceHid = new Guid("4D1E55B2-F16F-11CF-88CB-001111000030");
internal WinRawInput(WinWindowInfo parent)
#endregion
#region Constructors
public WinRawInput()
: base()
{
Debug.WriteLine("Initalizing windows raw input driver.");
Debug.Indent();
AssignHandle(parent.WindowHandle);
Debug.Print("Input window attached to parent {0}", parent);
keyboardDriver = new WinRawKeyboard(this.Handle);
mouseDriver = new WinRawMouse(this.Handle);
Debug.Unindent();
//AllocateBuffer();
Debug.WriteLine("Using WinRawInput.");
}
#endregion
#region internal static int DeviceCount
#region Private Members
internal static int DeviceCount
static IntPtr RegisterForDeviceNotifications(WinWindowInfo parent)
{
IntPtr dev_notify_handle;
BroadcastDeviceInterface bdi = new BroadcastDeviceInterface();
bdi.Size = BlittableValueType.StrideOf(bdi);
bdi.DeviceType = DeviceBroadcastType.INTERFACE;
bdi.ClassGuid = DeviceInterfaceHid;
unsafe
{
dev_notify_handle = Functions.RegisterDeviceNotification(parent.WindowHandle,
new IntPtr((void*)&bdi), DeviceNotification.WINDOW_HANDLE);
}
if (dev_notify_handle == IntPtr.Zero)
Debug.Print("[Warning] Failed to register for device notifications. Error: {0}", Marshal.GetLastWin32Error());
return dev_notify_handle;
}
#endregion
#region Protected Members
#region WindowProcedure
// Processes the input Windows Message, routing the buffer to the correct Keyboard, Mouse or HID.
protected override IntPtr WindowProcedure(
IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
switch (message)
{
case WindowMessage.INPUT:
int size = 0;
// Get the size of the input buffer
Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT,
IntPtr.Zero, ref size, API.RawInputHeaderSize);
// Read the actual raw input structure
if (size == Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT,
out data, ref size, API.RawInputHeaderSize))
{
switch (data.Header.Type)
{
case RawInputDeviceType.KEYBOARD:
if (((WinRawKeyboard)KeyboardDriver).ProcessKeyboardEvent(data))
return IntPtr.Zero;
break;
case RawInputDeviceType.MOUSE:
if (((WinRawMouse)MouseDriver).ProcessMouseEvent(data))
return IntPtr.Zero;
break;
case RawInputDeviceType.HID:
break;
}
}
break;
case WindowMessage.DEVICECHANGE:
((WinRawKeyboard)KeyboardDriver).RefreshDevices();
((WinRawMouse)MouseDriver).RefreshDevices();
break;
}
return base.WindowProcedure(handle, message, wParam, lParam);
}
#endregion
#region CreateDrivers
protected override void CreateDrivers()
{
keyboard_driver = new WinRawKeyboard(Parent.WindowHandle);
mouse_driver = new WinRawMouse(Parent.WindowHandle);
joystick_driver = new WinMMJoystick();
DevNotifyHandle = RegisterForDeviceNotifications(Parent);
}
#endregion
protected override void Dispose(bool manual)
{
if (!Disposed)
{
Functions.UnregisterDeviceNotification(DevNotifyHandle);
base.Dispose(manual);
}
}
#endregion
#region Public Members
#region DeviceCount
public static int DeviceCount
{
get
{
int deviceCount = 0;
Functions.GetRawInputDeviceList(null, ref deviceCount, API.RawInputDeviceListSize);
return deviceCount;
}
@ -62,200 +171,23 @@ namespace OpenTK.Platform.Windows
#endregion
#region protected override void WndProc(ref Message msg)
/// <summary>
/// Processes the input Windows Message, routing the buffer to the correct Keyboard, Mouse or HID.
/// </summary>
/// <param name="msg">The WM_INPUT message, containing the buffer on the input event.</param>
protected override void WndProc(ref Message msg)
{
switch ((WindowMessage)msg.Msg)
{
case WindowMessage.INPUT:
int size = 0;
// Get the size of the input buffer
Functions.GetRawInputData(msg.LParam, GetRawInputDataEnum.INPUT,
IntPtr.Zero, ref size, API.RawInputHeaderSize);
//if (buffer == null || API.RawInputSize < size)
//{
// throw new ApplicationException("Critical error when processing raw windows input.");
//}
if (size == Functions.GetRawInputData(msg.LParam, GetRawInputDataEnum.INPUT,
out data, ref size, API.RawInputHeaderSize))
{
switch (data.Header.Type)
{
case RawInputDeviceType.KEYBOARD:
if (!keyboardDriver.ProcessKeyboardEvent(data))
Functions.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize);
return;
case RawInputDeviceType.MOUSE:
if (!mouseDriver.ProcessEvent(data))
Functions.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize);
return;
case RawInputDeviceType.HID:
Functions.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize);
return;
default:
break;
}
}
else
{
throw new ApplicationException(String.Format(
"GetRawInputData returned invalid buffer. Windows error {0}. Please file a bug at http://opentk.sourceforge.net",
Marshal.GetLastWin32Error()));
}
break;
case WindowMessage.DESTROY:
Debug.Print("Input window detached from parent {0}.", Handle);
ReleaseHandle();
break;
case WindowMessage.QUIT:
Debug.WriteLine("Input window quit.");
this.Dispose();
break;
}
base.WndProc(ref msg);
}
#endregion
#region --- IInputDriver Members ---
#region IInputDriver2 Members
#region IInputDriver Members
public void Poll()
public override IKeyboardDriver2 KeyboardDriver
{
return;
#if false
// We will do a buffered read for all input devices and route the RawInput structures
// to the correct 'ProcessData' handlers. First, we need to find out the size of the
// buffer to allocate for the structures. Then we allocate the buffer and read the
// structures, calling the correct handler for each one. Last, we free the allocated
// buffer.
int size = 0;
Functions.GetRawInputBuffer(IntPtr.Zero, ref size, API.RawInputHeaderSize);
size *= 256;
IntPtr rin_data = Marshal.AllocHGlobal(size);
while (true)
{
// Iterate reading all available RawInput structures and routing them to their respective
// handlers.
int num = Functions.GetRawInputBuffer(rin_data, ref size, API.RawInputHeaderSize);
if (num == 0)
break;
else if (num < 0)
{
/*int error = Marshal.GetLastWin32Error();
if (error == 122)
{
// Enlarge the buffer, it was too small.
AllocateBuffer();
}
else
{
throw new ApplicationException(String.Format(
"GetRawInputBuffer failed with code: {0}", error));
}*/
Debug.Print("GetRawInputBuffer failed with code: {0}", Marshal.GetLastWin32Error());
//AllocateBuffer();
break;
}
RawInput[] rin_structs = new RawInput[num];
IntPtr next_rin = rin_data;
for (int i = 0; i < num; i++)
{
rin_structs[i] = (RawInput)Marshal.PtrToStructure(next_rin, typeof(RawInput));
switch (rin_structs[i].Header.Type)
{
case RawInputDeviceType.KEYBOARD:
keyboardDriver.ProcessKeyboardEvent(rin_structs[i]);
break;
case RawInputDeviceType.MOUSE:
mouseDriver.ProcessEvent(rin_structs[i]);
break;
}
next_rin = Functions.NextRawInputStructure(next_rin);
}
Functions.DefRawInputProc(rin_structs, num, (uint)API.RawInputHeaderSize);
}
Marshal.FreeHGlobal(rin_data);
#endif
get { return keyboard_driver; }
}
#endregion
#region IKeyboardDriver Members
public IList<KeyboardDevice> Keyboard
public override IMouseDriver2 MouseDriver
{
get { return keyboardDriver.Keyboard; }
get { return mouse_driver; }
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
public override IGamePadDriver GamePadDriver
{
get { return mouseDriver.Mouse; }
}
#endregion
#region IJoystickDriver Members
public IList<JoystickDevice> Joysticks
{
get { throw new NotImplementedException(); }
}
#endregion
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
{
keyboardDriver.Dispose();
this.ReleaseHandle();
}
disposed = true;
}
}
~WinRawInput()
{
Dispose(false);
get { return joystick_driver; }
}
#endregion

View file

@ -1,130 +1,247 @@
#region --- License ---
/* Copyright (c) 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#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
#region --- Using directives ---
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using OpenTK.Input;
#endregion
namespace OpenTK.Platform.Windows
{
internal class WinRawKeyboard : IKeyboardDriver, IDisposable
sealed class WinRawKeyboard : IKeyboardDriver2
{
private List<KeyboardDevice> keyboards = new List<KeyboardDevice>();
private IntPtr window;
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly List<KeyboardState> keyboards = new List<KeyboardState>();
readonly List<string> names = new List<string>();
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>();
readonly IntPtr window;
readonly object UpdateLock = new object();
#region --- Constructors ---
#region Constructors
internal WinRawKeyboard()
: this(IntPtr.Zero)
public WinRawKeyboard(IntPtr windowHandle)
{
}
internal WinRawKeyboard(IntPtr windowHandle)
{
Debug.WriteLine("Initializing keyboard driver (WinRawKeyboard).");
Debug.WriteLine("Using WinRawKeyboard.");
Debug.Indent();
this.window = windowHandle;
UpdateKeyboardList();
RefreshDevices();
Debug.Unindent();
}
#endregion
#region internal static void UpdateKeyboardList()
#region Public Members
internal void UpdateKeyboardList()
public void RefreshDevices()
{
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover keyboard devices:
for (int i = 0; i < count; i++)
lock (UpdateLock)
{
uint size = 0;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
if (name.ToLower().Contains("root"))
for (int i = 0; i < keyboards.Count; i++)
{
// This is a terminal services device, skip it.
continue;
KeyboardState state = keyboards[i];
state.IsConnected = false;
keyboards[i] = state;
}
else if (ridl[i].Type == RawInputDeviceType.KEYBOARD || ridl[i].Type == RawInputDeviceType.HID)
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover keyboard devices:
foreach (RawInputDeviceList dev in ridl)
{
// This is a keyboard or USB keyboard device. In the latter case, discover if it really is a
// keyboard device by qeurying the registry.
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
string deviceDesc =
(string)regkey.GetValue("DeviceDesc");
string deviceClass =
(string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
ContextHandle id = new ContextHandle(dev.Device);
if (rawids.ContainsKey(id))
{
KeyboardDevice kb = new KeyboardDevice();
kb.Description = deviceDesc;
// Device already registered, mark as connected
KeyboardState state = keyboards[rawids[id]];
state.IsConnected = true;
keyboards[rawids[id]] = state;
continue;
}
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
string name = GetDeviceName(dev);
if (name.ToLower().Contains("root"))
{
// This is a terminal services device, skip it.
continue;
}
else if (dev.Type == RawInputDeviceType.KEYBOARD || dev.Type == RawInputDeviceType.HID)
{
// This is a keyboard or USB keyboard device. In the latter case, discover if it really is a
// keyboard device by qeurying the registry.
RegistryKey regkey = GetRegistryKey(name);
string deviceDesc = (string)regkey.GetValue("DeviceDesc");
string deviceClass = (string)regkey.GetValue("Class");
kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
//kb.DeviceID = (info.Device.Keyboard.Type << 32) + info.Device.Keyboard.SubType;
kb.DeviceID = ridl[i].Device;
if (String.IsNullOrEmpty(deviceDesc))
{
Debug.Print("[Warning] Failed to retrieve device description, skipping this device.");
continue;
}
else
{
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
}
//if (!keyboards.Contains(kb))
//{
this.RegisterKeyboardDevice(kb);
keyboards.Add(kb);
//}
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
{
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
//KeyboardDevice kb = new KeyboardDevice();
//kb.Description = deviceDesc;
//kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
//kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
//kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
//kb.DeviceID = dev.Device;
RegisterKeyboardDevice(window, deviceDesc);
KeyboardState state = new KeyboardState();
state.IsConnected = true;
keyboards.Add(state);
names.Add(deviceDesc);
rawids.Add(new ContextHandle(dev.Device), keyboards.Count - 1);
}
}
}
}
}
public bool ProcessKeyboardEvent(RawInput rin)
{
bool processed = false;
bool pressed =
rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;
ContextHandle handle = new ContextHandle(rin.Header.Device);
KeyboardState keyboard;
if (!rawids.ContainsKey(handle))
{
RefreshDevices();
}
if (keyboards.Count == 0)
return false;
// Note:For some reason, my Microsoft Digital 3000 keyboard reports 0
// as rin.Header.Device for the "zoom-in/zoom-out" buttons.
// That's problematic, because no device has a "0" id.
// As a workaround, we'll add those buttons to the first device (if any).
int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;
keyboard = keyboards[keyboard_handle];
// Generic control, shift, alt keys may be sent instead of left/right.
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey)
{
case VirtualKeys.SHIFT:
keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed;
processed = true;
break;
case VirtualKeys.CONTROL:
keyboard[Input.Key.ControlLeft] = keyboard[Input.Key.ControlRight] = pressed;
processed = true;
break;
case VirtualKeys.MENU:
keyboard[Input.Key.AltLeft] = keyboard[Input.Key.AltRight] = pressed;
processed = true;
break;
default:
if (!KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
{
Debug.Print("Virtual key {0} ({1}) not mapped.",
rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
}
else
{
keyboard[KeyMap[rin.Data.Keyboard.VKey]] = pressed;
processed = true;
}
break;
}
lock (UpdateLock)
{
keyboards[keyboard_handle] = keyboard;
return processed;
}
}
#endregion
#region internal void RegisterKeyboardDevice(Keyboard kb)
#region Private Members
internal void RegisterKeyboardDevice(KeyboardDevice kb)
static RegistryKey GetRegistryKey(string name)
{
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
return regkey;
}
static string GetDeviceName(RawInputDeviceList dev)
{
uint size = 0;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
return name;
}
static void RegisterKeyboardDevice(IntPtr window, string name)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
@ -136,134 +253,52 @@ namespace OpenTK.Platform.Windows
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
throw new ApplicationException(
String.Format(
"Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(),
rid[0].ToString())
);
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered keyboard {0}", kb.ToString());
Debug.Print("Registered keyboard {0}", name);
}
}
#endregion
#region internal bool ProcessKeyboardEvent(API.RawInput rin)
#region IKeyboardDriver2 Members
/// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessKeyboardEvent(RawInput rin)
public KeyboardState GetState()
{
//Keyboard key = keyboards[0];
//rin.Header.Device;
switch (rin.Header.Type)
lock (UpdateLock)
{
case RawInputDeviceType.KEYBOARD:
bool pressed =
rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;
// Find the device where the button was pressed. It can be that the input notification
// came not from a physical keyboard device but from a code-generated input message - in
// that case, the event goes to the default (first) keyboard.
// TODO: Send the event to all keyboards instead of the default one.
// TODO: Optimize this! The predicate allocates way to much memory.
//int index = keyboards.FindIndex(delegate(KeyboardDevice kb)
//{
// return kb.DeviceID == rin.Header.Device;
//});
//if (index == -1) index = 0;
int index;
if (keyboards.Count > 0) index = 0;
else return false;
// Generic control, shift, alt keys may be sent instead of left/right.
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey)
{
case VirtualKeys.SHIFT:
keyboards[index][Input.Key.ShiftLeft] = keyboards[index][Input.Key.ShiftRight] = pressed;
return true;
case VirtualKeys.CONTROL:
keyboards[index][Input.Key.ControlLeft] = keyboards[index][Input.Key.ControlRight] = pressed;
return true;
case VirtualKeys.MENU:
keyboards[index][Input.Key.AltLeft] = keyboards[index][Input.Key.AltRight] = pressed;
return true;
default:
if (!WMInput.KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
Debug.Print("Virtual key {0} ({1}) not mapped.",
rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
else
keyboards[index][WMInput.KeyMap[rin.Data.Keyboard.VKey]] = pressed;
return false;
}
default:
throw new ApplicationException("Windows raw keyboard driver received invalid data.");
}
}
#endregion
#region --- IInputDevice Members ---
public string Description
{
get { throw new Exception("The method or operation is not implemented."); }
}
public Input.InputDeviceType DeviceType
{
get { return Input.InputDeviceType.Keyboard; }
}
#endregion
#region --- IKeyboardDriver Members ---
public IList<KeyboardDevice> Keyboard
{
get { return keyboards; }
}
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
KeyboardState master = new KeyboardState();
foreach (KeyboardState ks in keyboards)
{
keyboards.Clear();
master.MergeBits(ks);
}
disposed = true;
return master;
}
}
~WinRawKeyboard()
public KeyboardState GetState(int index)
{
Dispose(false);
lock (UpdateLock)
{
if (keyboards.Count > index)
return keyboards[index];
else
return new KeyboardState();
}
}
public string GetDeviceName(int index)
{
lock (UpdateLock)
{
if (names.Count > index)
return names[index];
else
return String.Empty;
}
}
#endregion

View file

@ -1,17 +1,36 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#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.Text;
using OpenTK.Input;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Drawing;
using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
@ -19,121 +38,198 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Contains methods to register for and process mouse WM_INPUT messages.
/// </summary>
internal class WinRawMouse : IMouseDriver, IDisposable
sealed class WinRawMouse : IMouseDriver2
{
private List<MouseDevice> mice = new List<MouseDevice>();
private IntPtr window;
readonly List<MouseState> mice = new List<MouseState>();
readonly List<string> names = new List<string>();
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>();
readonly IntPtr Window;
readonly object UpdateLock = new object();
#region --- Constructors ---
#region Constructors
internal WinRawMouse()
: this(IntPtr.Zero)
public WinRawMouse(IntPtr window)
{
}
internal WinRawMouse(IntPtr windowHandle)
{
Debug.WriteLine("Initializing mouse driver (WinRawMouse).");
Debug.WriteLine("Using WinRawMouse.");
Debug.Indent();
this.window = windowHandle;
if (window == IntPtr.Zero)
throw new ArgumentNullException("window");
RegisterDevices();
Window = window;
RefreshDevices();
Debug.Unindent();
}
#endregion
#region --- IMouseDriver Members ---
#region Public Members
public IList<MouseDevice> Mouse
public void RefreshDevices()
{
get { return mice; }
}
#region public int RegisterDevices()
public int RegisterDevices()
{
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover mouse devices:
for (int i = 0; i < count; i++)
lock (UpdateLock)
{
uint size = 0;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
if (name.ToLower().Contains("root"))
// Mark all devices as disconnected. We will check which of those
// are connected later on.
for (int i = 0; i < mice.Count; i++)
{
// This is a terminal services device, skip it.
continue;
MouseState state = mice[i];
state.IsConnected = false;
mice[i] = state;
}
else if (ridl[i].Type == RawInputDeviceType.MOUSE || ridl[i].Type == RawInputDeviceType.HID)
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover mouse devices
foreach (RawInputDeviceList dev in ridl)
{
// This is a mouse or a USB mouse device. In the latter case, discover if it really is a
// mouse device by qeurying the registry.
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
string deviceDesc = (string)regkey.GetValue("DeviceDesc");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
string deviceClass = (string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
ContextHandle id = new ContextHandle(dev.Device);
if (rawids.ContainsKey(id))
{
OpenTK.Input.MouseDevice mouse = new OpenTK.Input.MouseDevice();
mouse.Description = deviceDesc;
// Device already registered, mark as connected
MouseState state = mice[rawids[id]];
state.IsConnected = true;
mice[rawids[id]] = state;
continue;
}
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
// Unregistered device, find what it is
string name = GetDeviceName(dev);
if (name.ToLower().Contains("root"))
{
// This is a terminal services device, skip it.
continue;
}
else if (dev.Type == RawInputDeviceType.MOUSE || dev.Type == RawInputDeviceType.HID)
{
// This is a mouse or a USB mouse device. In the latter case, discover if it really is a
// mouse device by qeurying the registry.
RegistryKey regkey = FindRegistryKey(name);
string deviceDesc = (string)regkey.GetValue("DeviceDesc");
string deviceClass = (string)regkey.GetValue("Class");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
mouse.NumberOfButtons = info.Device.Mouse.NumberOfButtons;
mouse.NumberOfWheels = info.Device.Mouse.HasHorizontalWheel ? 1 : 0;
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
{
if (!rawids.ContainsKey(new ContextHandle(dev.Device)))
{
// Register the device:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
mouse.DeviceID = ridl[i].Device;//(IntPtr)info.Device.Mouse.Id;
this.RegisterRawDevice(mouse);
mice.Add(mouse);
RegisterRawDevice(Window, deviceDesc);
MouseState state = new MouseState();
state.IsConnected = true;
mice.Add(state);
names.Add(deviceDesc);
rawids.Add(new ContextHandle(dev.Device), mice.Count - 1);
}
}
}
}
}
}
return count;
public bool ProcessMouseEvent(RawInput rin)
{
RawMouse raw = rin.Data.Mouse;
ContextHandle handle = new ContextHandle(rin.Header.Device);
MouseState mouse;
if (!rawids.ContainsKey(handle))
{
RefreshDevices();
}
if (mice.Count == 0)
return false;
// Note:For some reason, my Microsoft Digital 3000 keyboard reports 0
// as rin.Header.Device for the "zoom-in/zoom-out" buttons.
// That's problematic, because no device has a "0" id.
// As a workaround, we'll add those buttons to the first device (if any).
int mouse_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;
mouse = mice[mouse_handle];
if ((raw.ButtonFlags & RawInputMouseState.LEFT_BUTTON_DOWN) != 0) mouse.EnableBit((int)MouseButton.Left);
if ((raw.ButtonFlags & RawInputMouseState.LEFT_BUTTON_UP) != 0) mouse.DisableBit((int)MouseButton.Left);
if ((raw.ButtonFlags & RawInputMouseState.RIGHT_BUTTON_DOWN) != 0) mouse.EnableBit((int)MouseButton.Right);
if ((raw.ButtonFlags & RawInputMouseState.RIGHT_BUTTON_UP) != 0) mouse.DisableBit((int)MouseButton.Right);
if ((raw.ButtonFlags & RawInputMouseState.MIDDLE_BUTTON_DOWN) != 0) mouse.EnableBit((int)MouseButton.Middle);
if ((raw.ButtonFlags & RawInputMouseState.MIDDLE_BUTTON_UP) != 0) mouse.DisableBit((int)MouseButton.Middle);
if ((raw.ButtonFlags & RawInputMouseState.BUTTON_4_DOWN) != 0) mouse.EnableBit((int)MouseButton.Button1);
if ((raw.ButtonFlags & RawInputMouseState.BUTTON_4_UP) != 0) mouse.DisableBit((int)MouseButton.Button1);
if ((raw.ButtonFlags & RawInputMouseState.BUTTON_5_DOWN) != 0) mouse.EnableBit((int)MouseButton.Button2);
if ((raw.ButtonFlags & RawInputMouseState.BUTTON_5_UP) != 0) mouse.DisableBit((int)MouseButton.Button2);
if ((raw.ButtonFlags & RawInputMouseState.WHEEL) != 0)
mouse.WheelPrecise += (short)raw.ButtonData / 120.0f;
if ((raw.Flags & RawMouseFlags.MOUSE_MOVE_ABSOLUTE) != 0)
{
mouse.X = raw.LastX;
mouse.Y = raw.LastY;
}
else
{ // Seems like MOUSE_MOVE_RELATIVE is the default, unless otherwise noted.
mouse.X += raw.LastX;
mouse.Y += raw.LastY;
}
lock (UpdateLock)
{
mice[mouse_handle] = mouse;
return true;
}
}
#endregion
#endregion
#region Private Members
#region internal void RegisterRawDevice(OpenTK.Input.Mouse mouse)
static string GetDeviceName(RawInputDeviceList dev)
{
// get name size
uint size = 0;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
internal void RegisterRawDevice(OpenTK.Input.MouseDevice mouse)
// get actual name
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
return name;
}
static RegistryKey FindRegistryKey(string name)
{
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
return regkey;
}
static void RegisterRawDevice(IntPtr window, string device)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Mouse is 1/2 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
@ -145,113 +241,46 @@ namespace OpenTK.Platform.Windows
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
throw new ApplicationException(
String.Format(
"Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(),
rid[0].ToString())
);
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered mouse {0}", mouse.ToString());
Point p = new Point();
if (Functions.GetCursorPos(ref p))
mouse.Position = p;
Debug.Print("Registered mouse {0}", device);
}
}
#endregion
#region internal bool ProcessEvent(API.RawInput rin)
#region IMouseDriver2 Members
/// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessEvent(RawInput rin)
public MouseState GetState()
{
//MouseDevice mouse = mice.Find(delegate(MouseDevice m)
//{
// return m.DeviceID == rin.Header.Device;
//});
MouseDevice mouse;
if (mice.Count > 0) mouse = mice[0];
else return false;
switch (rin.Header.Type)
lock (UpdateLock)
{
case RawInputDeviceType.MOUSE:
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.LEFT_BUTTON_DOWN) != 0) mouse[MouseButton.Left] = true;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.LEFT_BUTTON_UP) != 0) mouse[MouseButton.Left] = false;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.RIGHT_BUTTON_DOWN) != 0) mouse[MouseButton.Right] = true;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.RIGHT_BUTTON_UP) != 0) mouse[MouseButton.Right] = false;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.MIDDLE_BUTTON_DOWN) != 0) mouse[MouseButton.Middle] = true;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.MIDDLE_BUTTON_UP) != 0) mouse[MouseButton.Middle] = false;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.BUTTON_4_DOWN) != 0) mouse[MouseButton.Button1] = true;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.BUTTON_4_UP) != 0) mouse[MouseButton.Button1] = false;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.BUTTON_5_DOWN) != 0) mouse[MouseButton.Button2] = true;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.BUTTON_5_UP) != 0) mouse[MouseButton.Button2] = false;
if ((rin.Data.Mouse.ButtonFlags & RawInputMouseState.WHEEL) != 0)
mouse.Wheel += (short)rin.Data.Mouse.ButtonData / 120;
if ((rin.Data.Mouse.Flags & RawMouseFlags.MOUSE_MOVE_ABSOLUTE) != 0)
{
mouse.Position = new Point(rin.Data.Mouse.LastX, rin.Data.Mouse.LastY);
}
else
{ // Seems like MOUSE_MOVE_RELATIVE is the default, unless otherwise noted.
mouse.Position = new Point(mouse.X + rin.Data.Mouse.LastX,
mouse.Y + rin.Data.Mouse.LastY);
}
if ((rin.Data.Mouse.Flags & RawMouseFlags.MOUSE_VIRTUAL_DESKTOP) != 0)
Debug.WriteLine(String.Format("Mouse {0} defines MOUSE_VIRTUAL_DESKTOP flag, please report at http://www.opentk.com", mouse.ToString()));
return true;
default:
throw new ApplicationException("WinRawMouse driver received invalid data.");
}
}
#endregion
#region public void Poll()
public void Poll()
{
}
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
MouseState master = new MouseState();
foreach (MouseState ms in mice)
{
mice.Clear();
master.MergeBits(ms);
}
disposed = true;
return master;
}
}
~WinRawMouse()
public MouseState GetState(int index)
{
Dispose(false);
lock (UpdateLock)
{
if (mice.Count > index)
return mice[index];
else
return new MouseState();
}
}
public void SetPosition(double x, double y)
{
Functions.SetCursorPos((int)x, (int)y);
}
#endregion

View file

@ -1142,6 +1142,8 @@ XF86VidModeGetGammaRampSize(
Hyper_L = 0xffed, /* Left hyper */
Hyper_R = 0xffee, /* Right hyper */
ISO_Level3_Shift = 0xfe03,
/*
* Latin 1
* (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
@ -1245,6 +1247,79 @@ XF86VidModeGetGammaRampSize(
bar = 0x007c, /* U+007C VERTICAL LINE */
braceright = 0x007d, /* U+007D RIGHT CURLY BRACKET */
asciitilde = 0x007e, /* U+007E TILDE */
// Extra keys
XF86AudioMute = 0x1008ff12,
XF86AudioLowerVolume = 0x1008ff11,
XF86AudioRaiseVolume = 0x1008ff13,
XF86PowerOff = 0x1008ff2a,
XF86Suspend = 0x1008ffa7,
XF86Copy = 0x1008ff57,
XF86Paste = 0x1008ff6d,
XF86Cut = 0x1008ff58,
XF86MenuKB = 0x1008ff65,
XF86Calculator = 0x1008ff1d,
XF86Sleep = 0x1008ff2f,
XF86WakeUp = 0x1008ff2b ,
XF86Explorer = 0x1008ff5d,
XF86Send = 0x1008ff7b,
XF86Xfer = 0x1008ff8a,
XF86Launch1 = 0x1008ff41,
XF86Launch2 = 0x1008ff42,
XF86Launch3 = 0x1008ff43,
XF86Launch4 = 0x1008ff44,
XF86Launch5 = 0x1008ff45,
XF86LaunchA = 0x1008ff4a,
XF86LaunchB = 0x1008ff4b,
XF86WWW = 0x1008ff2e,
XF86DOS = 0x1008ff5a,
XF86ScreenSaver = 0x1008ff2d,
XF86RotateWindows = 0x1008ff74,
XF86Mail = 0x1008ff19,
XF86Favorites = 0x1008ff30,
XF86MyComputer = 0x1008ff33,
XF86Back = 0x1008ff26,
XF86Forward = 0x1008ff27 ,
XF86Eject = 0x1008ff2c,
XF86AudioPlay = 0x1008ff14,
XF86AudioStop = 0x1008ff15,
XF86AudioPrev = 0x1008ff16,
XF86AudioNext = 0x1008ff17,
XF86AudioRecord = 0x1008ff1c,
XF86AudioPause =0x1008ff31,
XF86AudioRewind = 0x1008ff3e,
XF86AudioForward = 0x1008ff97,
XF86Phone = 0x1008ff6e,
XF86Tools = 0x1008ff81,
XF86HomePage = 0x1008ff18,
XF86Close = 0x1008ff56,
XF86Reload = 0x1008ff73,
XF86ScrollUp = 0x1008ff78,
XF86ScrollDown = 0x1008ff79,
XF86New = 0x1008ff68,
XF86TouchpadToggle = 0x1008ffa9,
XF86WebCam = 0x1008ff8f,
XF86Search = 0x1008ff1b,
XF86Finance = 0x1008ff3c,
XF86Shop = 0x1008ff36,
XF86MonBrightnessDown = 0x1008ff03,
XF86MonBrightnessUp = 0x1008ff02,
XF86AudioMedia = 0x1008ff32,
XF86Display = 0x1008ff59,
XF86KbdLightOnOff = 0x1008ff04,
XF86KbdBrightnessDown = 0x1008ff06,
XF86KbdBrightnessUp = 0x1008ff05,
XF86Reply = 0x1008ff72,
XF86MailForward = 0x1008ff90,
XF86Save = 0x1008ff77,
XF86Documents = 0x1008ff5b,
XF86Battery = 0x1008ff93,
XF86Bluetooth = 0x1008ff94,
XF86WLAN = 0x1008ff95,
SunProps = 0x1005ff70,
SunOpen = 0x1005ff73,
}
#endregion
@ -1426,7 +1501,7 @@ XF86VidModeGetGammaRampSize(
[DllImport(XrandrLibrary)]
public static extern Status XRRSetScreenConfig(Display dpy, XRRScreenConfiguration config,
Drawable draw, int size_index, ref Rotation rotation, Time timestamp);
Drawable draw, int size_index, Rotation rotation, Time timestamp);
[DllImport(XrandrLibrary)]
public static extern Status XRRSetScreenConfigAndRate(Display dpy, XRRScreenConfiguration config,
@ -1562,6 +1637,26 @@ XF86VidModeGetGammaRampSize(
#endregion
#endregion
public static Pixmap XCreateBitmapFromData(Display display, Window d, byte[,] data)
{
if (data == null)
throw new ArgumentNullException("data");
unsafe
{
fixed (byte* pdata = data)
{
return XCreateBitmapFromData(display, d, pdata, data.GetLength(0), data.GetLength(1));
}
}
}
[DllImport(X11Library)]
unsafe public static extern Pixmap XCreateBitmapFromData(Display display, Window d, byte* data, int width, int height);
[DllImport("libX11", EntryPoint = "XAllocColor")]
public static extern Status XAllocNamedColor(Display display, Colormap colormap, string color_name, out XColor screen_def_return, out XColor exact_def_return);
}
/*
[StructLayout(LayoutKind.Sequential)]
@ -1618,6 +1713,19 @@ XF86VidModeGetGammaRampSize(
Functions.XUnlockDisplay(Display);
}
}
// XAllowEvent modes
enum EventMode
{
AsyncPointer = 0,
SyncPointer,
ReplayPointer,
AsyncKeyboard,
SyncKeyboard,
ReplayKeyboard,
AsyncBoth,
SyncBoth
}
}
#pragma warning restore 3019

View file

@ -27,7 +27,7 @@ namespace OpenTK.Platform.X11
using Mask = System.IntPtr;
using Atom = System.IntPtr;
using VisualID = System.IntPtr;
using Time = System.UInt32;
using Time = System.IntPtr;
using KeyCode = System.Byte; // Or maybe ushort?
using Display = System.IntPtr;
@ -94,13 +94,23 @@ namespace OpenTK.Platform.X11
public extern static Bool XCheckWindowEvent(Display display, Window w, EventMask event_mask, ref XEvent event_return);
[DllImport("libX11")]
public extern static Bool XCheckTypedWindowEvent(Display display, Window w, XEventName event_type, ref XEvent event_return);
[DllImport("libX11")]
public extern static Bool XCheckTypedEvent(Display display, XEventName event_type, out XEvent event_return);
public delegate Bool EventPredicate(IntPtr display, ref XEvent e, IntPtr arg);
[DllImport("libX11")]
public extern static Bool XIfEvent(Display display, ref XEvent e, IntPtr predicate, IntPtr arg );
[DllImport("libX11")]
public extern static Bool XCheckIfEvent(Display display, ref XEvent e, IntPtr predicate, IntPtr arg );
[DllImport("libX11")]
public extern static int XConnectionNumber(IntPtr diplay);
[DllImport("libX11")]
public extern static int XPending(IntPtr diplay);
[DllImport("libX11", EntryPoint = "XSelectInput")]
public extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
public extern static int XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
[DllImport("libX11", EntryPoint = "XDestroyWindow")]
public extern static int XDestroyWindow(IntPtr display, IntPtr window);
@ -170,12 +180,41 @@ namespace OpenTK.Platform.X11
[DllImport("libX11", EntryPoint = "XUngrabPointer")]
public extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
[DllImport("libX11", EntryPoint = "XGrabButton")]
public extern static int XGrabButton(IntPtr display,
int button, uint modifiers, Window grab_window,
Bool owner_events, EventMask event_mask,
GrabMode pointer_mode, GrabMode keyboard_mode,
Window confine_to, Cursor cursor);
[DllImport("libX11", EntryPoint = "XUngrabButton")]
public extern static int XUngrabButton(IntPtr display, uint button, uint
modifiers, Window grab_window);
[DllImport("libX11", EntryPoint = "XQueryPointer")]
public extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
[DllImport("libX11", EntryPoint = "XTranslateCoordinates")]
public extern static bool XTranslateCoordinates(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return, out int dest_y_return, out IntPtr child_return);
[DllImport("libX11")]
public extern static int XGrabKey(IntPtr display, int keycode, uint modifiers,
Window grab_window, bool owner_events, GrabMode pointer_mode, GrabMode keyboard_mode);
[DllImport("libX11")]
public extern static int XUngrabKey(IntPtr display, int keycode, uint modifiers, Window grab_window);
[DllImport("libX11", EntryPoint = "XGrabKeyboard")]
public extern static int XGrabKeyboard(IntPtr display, IntPtr window, bool owner_events,
GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr timestamp);
[DllImport("libX11", EntryPoint = "XUngrabKeyboard")]
public extern static int XUngrabKeyboard(IntPtr display, IntPtr timestamp);
[DllImport("libX11")]
public extern static int XAllowEvents(IntPtr display, EventMode event_mode, Time time);
[DllImport("libX11", EntryPoint = "XGetGeometry")]
public extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
@ -319,7 +358,7 @@ namespace OpenTK.Platform.X11
public extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
[DllImport("libX11", EntryPoint = "XQueryExtension")]
public extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
public extern static int XQueryExtension(IntPtr display, string extension_name, out int major, out int first_event, out int first_error);
[DllImport("libX11", EntryPoint = "XWhitePixel")]
public extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
@ -453,9 +492,49 @@ namespace OpenTK.Platform.X11
public static extern int XLookupString(ref XKeyEvent event_struct, [Out] byte[] buffer_return,
int bytes_buffer, [Out] KeySym[] keysym_return, IntPtr status_in_out);
[DllImport("libX11")]
public static extern KeyCode XKeysymToKeycode(IntPtr display, KeySym keysym);
[DllImport("libX11")]
public static extern KeySym XKeycodeToKeysym(IntPtr display, KeyCode keycode, int index);
[DllImport("libX11")]
public static extern int XRefreshKeyboardMapping(ref XMappingEvent event_map);
[DllImport("libX11")]
public static extern int XGetEventData(IntPtr display, ref XGenericEventCookie cookie);
[DllImport("libX11")]
public static extern void XFreeEventData(IntPtr display, ref XGenericEventCookie cookie);
[DllImport("libXi")]
static extern int XISelectEvents(IntPtr dpy, Window win, [In] XIEventMask[] masks, int num_masks);
[DllImport("libXi")]
static extern int XISelectEvents(IntPtr dpy, Window win, [In] ref XIEventMask masks, int num_masks);
public static int XISelectEvents(IntPtr dpy, Window win, XIEventMask[] masks)
{
return XISelectEvents(dpy, win, masks, masks.Length);
}
public static int XISelectEvents(IntPtr dpy, Window win, XIEventMask mask)
{
return XISelectEvents(dpy, win, ref mask, 1);
}
[DllImport("libXi")]
static extern Status XIGrabDevice(IntPtr display, int deviceid, Window grab_window, Time time,
Cursor cursor, int grab_mode, int paired_device_mode, Bool owner_events, XIEventMask[] mask);
[DllImport("libXi")]
static extern Status XIUngrabDevice(IntPtr display, int deviceid, Time time);
[DllImport("libXi")]
public static extern Bool XIWarpPointer(Display display,
int deviceid, Window src_w, Window dest_w,
double src_x, double src_y, int src_width, int src_height,
double dest_x, double dest_y);
static readonly IntPtr CopyFromParent = IntPtr.Zero;
public static void SendNetWMMessage(X11WindowInfo window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)

Some files were not shown because too many files have changed in this diff Show more