EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testDrm", "testDrm\testDrm.csproj", "{4B57740A-75FB-4978-A8E8-8B1793B7474F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DRI.net", "..\DRI.net\DRI.net.csproj", "{0189EAEF-DCD4-42F8-A83A-2DEA82926671}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Release|Any CPU.Build.0 = Release|Any CPU
{4B57740A-75FB-4978-A8E8-8B1793B7474F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B57740A-75FB-4978-A8E8-8B1793B7474F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B57740A-75FB-4978-A8E8-8B1793B7474F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B57740A-75FB-4978-A8E8-8B1793B7474F}.Release|Any CPU.Build.0 = Release|Any CPU
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.Build.0 = Release|Any CPU
{A37A7E14-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A37A7E14-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.Build.0 = Release|Any CPU
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
</CustomCommands>
<ReleaseVersion>0.5</ReleaseVersion>
<StartupObject>CrowIDE.CrowIDE</StartupObject>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <ConsolePause>false</ConsolePause>
<IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
<OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
</PropertyGroup>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Drawing" />
- <Reference Include="OpenTK">
- <HintPath>$(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
- <Package>opentk</Package>
- </Reference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project>
<Name>Crow</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\DRI.net\DRI.net.csproj">
+ <Project>{0189EAEF-DCD4-42F8-A83A-2DEA82926671}</Project>
+ <Name>DRI.net</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
- <Compile Include="OpenTKGameWindow.cs" />
- <Compile Include="OpenGL\Shader.cs" />
- <Compile Include="OpenGL\Texture.cs" />
- <Compile Include="OpenGL\vaoMesh.cs" />
- <Compile Include="src\CrowIDE.cs" />
<Compile Include="src\ImlVisualEditor.cs" />
<Compile Include="src\MembersView.cs" />
<Compile Include="src\Extensions.cs" />
<Compile Include="src\Microsoft.Build.CommonTypes.cs" />
+ <Compile Include="src\CrowIDEdrm.cs" />
+ <Compile Include="src\Application.cs" />
+ <Compile Include="src\Signal.cs" />
+ <Compile Include="src\Bindings\Evdev.cs" />
+ <Compile Include="src\Bindings\LibInput.cs" />
+ <Compile Include="src\Bindings\Udev.cs" />
+ <Compile Include="src\DRIControler.cs" />
+ <Compile Include="src\BlittableValueType.cs">
+ <SubType>Code</SubType>
+ </Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="ui\" />
<None Include="ui\test.crow">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
+ <None Include="src\CrowIDE.cs" />
</ItemGroup>
</Project>
+++ /dev/null
-//
-// Shader.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-
-namespace Crow
-{
- public class Shader : IDisposable
- {
- #region CTOR
- public Shader ()
- {
- Init ();
- }
- public Shader (string vertResPath, string fragResPath = null, string geomResPath = null)
- {
- VertSourcePath = vertResPath;
- FragSourcePath = fragResPath;
- GeomSourcePath = geomResPath;
-
- loadSourcesFiles ();
-
- Init ();
- }
- #endregion
-
- public string VertSourcePath,
- FragSourcePath,
- GeomSourcePath;
- #region Sources
- protected string _vertSource = @"
- #version 330
- precision lowp float;
-
- uniform mat4 mvp;
-
- layout(location = 0) in vec3 in_position;
- layout(location = 1) in vec2 in_tex;
-
- out vec2 texCoord;
-
- void main(void)
- {
- texCoord = in_tex;
- gl_Position = mvp * vec4(in_position, 1.0);
- }";
-
- protected string _fragSource = @"
- #version 330
- precision lowp float;
-
- uniform sampler2D tex;
-
- in vec2 texCoord;
- out vec4 out_frag_color;
-
- void main(void)
- {
- out_frag_color = texture( tex, texCoord);//vec4(1,0,0,1);
- }";
- string _geomSource = @"";
-// #version 330
-// layout(triangles) in;
-// layout(triangle_strip, max_vertices=3) out;
-// void main()
-// {
-// for(int i=0; i<3; i++)
-// {
-// gl_Position = gl_in[i].gl_Position;
-// EmitVertex();
-// }
-// EndPrimitive();
-// }";
- #endregion
-
- #region Private and protected fields
- public int vsId, fsId, gsId, pgmId, mvpLocation;
-
- Matrix4 mvp = Matrix4.Identity;
- #endregion
-
-
- #region Public properties
- public virtual string vertSource
- {
- get { return _vertSource;}
- set { _vertSource = value; }
- }
- public virtual string fragSource
- {
- get { return _fragSource;}
- set { _fragSource = value; }
- }
- public virtual string geomSource
- {
- get { return _geomSource; }
- set { _geomSource = value; }
- }
-
- public virtual Matrix4 MVP{
- set { mvp = value; }
- get { return mvp; }
- }
- #endregion
-
- #region Public functions
- /// <summary>
- /// configure sources and compile
- /// </summary>
- public virtual void Init()
- {
- Compile ();
- }
- public void Reload(){
- loadSourcesFiles ();
- Compile ();
- }
- public void SetSource(ShaderType shaderType, string _source){
- switch (shaderType) {
- case ShaderType.FragmentShader:
- fragSource = _source;
- return;
- case ShaderType.VertexShader:
- vertSource = _source;
- return;
- case ShaderType.GeometryShader:
- geomSource = _source;
- return;
- }
- }
- public string GetSource(ShaderType shaderType){
- switch (shaderType) {
- case ShaderType.FragmentShader:
- return fragSource;
- case ShaderType.VertexShader:
- return vertSource;
- case ShaderType.GeometryShader:
- return geomSource;
- }
- return "";
- }
- public string GetSourcePath(ShaderType shaderType){
- switch (shaderType) {
- case ShaderType.FragmentShader:
- return FragSourcePath;
- case ShaderType.VertexShader:
- return VertSourcePath;
- case ShaderType.GeometryShader:
- return GeomSourcePath;
- }
- return "";
- }
- public virtual void Compile()
- {
- Dispose ();
-
- pgmId = GL.CreateProgram();
-
- if (!string.IsNullOrEmpty(vertSource))
- {
- vsId = GL.CreateShader(ShaderType.VertexShader);
- compileShader(vsId, vertSource);
- }
- if (!string.IsNullOrEmpty(fragSource))
- {
- fsId = GL.CreateShader(ShaderType.FragmentShader);
- compileShader(fsId, fragSource);
-
- }
- if (!string.IsNullOrEmpty(geomSource))
- {
- gsId = GL.CreateShader(ShaderType.GeometryShader);
- compileShader(gsId,geomSource);
- }
-
- if (vsId != 0)
- GL.AttachShader(pgmId, vsId);
- if (fsId != 0)
- GL.AttachShader(pgmId, fsId);
- if (gsId != 0)
- GL.AttachShader(pgmId, gsId);
-
- BindVertexAttributes ();
-
- string info;
- GL.LinkProgram(pgmId);
- GL.GetProgramInfoLog(pgmId, out info);
-
- if (!string.IsNullOrEmpty (info)) {
- Debug.WriteLine ("Linkage:");
- Debug.WriteLine (info);
- }
-
- info = null;
-
- GL.ValidateProgram(pgmId);
- GL.GetProgramInfoLog(pgmId, out info);
- if (!string.IsNullOrEmpty (info)) {
- Debug.WriteLine ("Validation:");
- Debug.WriteLine (info);
- }
-
- GL.UseProgram (pgmId);
-
- GetUniformLocations ();
- BindSamplesSlots ();
-
- Disable ();
- }
-
- protected virtual void BindVertexAttributes()
- {
- GL.BindAttribLocation(pgmId, 0, "in_position");
- GL.BindAttribLocation(pgmId, 1, "in_tex");
- }
- protected virtual void GetUniformLocations()
- {
- mvpLocation = GL.GetUniformLocation(pgmId, "mvp");
- }
- protected virtual void BindSamplesSlots(){
- GL.Uniform1(GL.GetUniformLocation (pgmId, "tex"), 0);
- }
- public void SetMVP(Matrix4 _mvp){
- GL.UniformMatrix4(mvpLocation, false, ref _mvp);
- }
- public virtual void Enable(){
- GL.UseProgram (pgmId);
- }
- public virtual void Disable(){
- GL.UseProgram (0);
- }
- public static void Enable(Shader s)
- {
- if (s == null)
- return;
- s.Enable ();
- }
- public static void Disable(Shader s)
- {
- if (s == null)
- return;
- s.Disable ();
- }
- #endregion
-
- void loadSourcesFiles(){
- Stream s;
-
- if (!string.IsNullOrEmpty (VertSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (VertSourcePath);
- if (s != null) {
- using (StreamReader sr = new StreamReader (s)) {
- vertSource = sr.ReadToEnd ();
- }
- }
- }
-
- if (!string.IsNullOrEmpty (FragSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (FragSourcePath);
- if (s != null) {
- using (StreamReader sr = new StreamReader (s)) {
- fragSource = sr.ReadToEnd ();
- }
- }
- }
-
- if (!string.IsNullOrEmpty (GeomSourcePath)) {
- s = Crow.Interface.GetStreamFromPath (GeomSourcePath);
- if (s != null) {
- using (StreamReader sr = new StreamReader (s)) {
- geomSource = sr.ReadToEnd ();
- }
- }
- }
- }
- void compileShader(int shader, string source)
- {
- GL.ShaderSource(shader, source);
- GL.CompileShader(shader);
-
- string info;
- GL.GetShaderInfoLog(shader, out info);
- Debug.WriteLine(info);
-
- int compileResult;
- GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
- if (compileResult != 1)
- {
- Debug.WriteLine("Compile Error!");
- Debug.WriteLine(source);
- }
- }
- public override string ToString ()
- {
- return string.Format ("{0} {1} {2}", VertSourcePath, FragSourcePath, GeomSourcePath);
- }
-
- #region IDisposable implementation
- public virtual void Dispose ()
- {
- if (GL.IsProgram (pgmId))
- GL.DeleteProgram (pgmId);
-
- if (GL.IsShader (vsId))
- GL.DeleteShader (vsId);
- if (GL.IsShader (fsId))
- GL.DeleteShader (fsId);
- if (GL.IsShader (gsId))
- GL.DeleteShader (gsId);
- }
- #endregion
- }
-}
+++ /dev/null
-//
-// Texture.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-using System;
-using System.Drawing;
-using OpenTK.Graphics.OpenGL;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Diagnostics;
-
-namespace Crow
-{
- public class Texture
- {
- public string Map;
- public int texRef;
- public int Width;
- public int Height;
-
- public Texture(string _mapPath, bool flipY = true)
- {
- using (Stream s = Interface.GetStreamFromPath (_mapPath)) {
-
- try {
- Map = _mapPath;
-
- Bitmap bitmap = new Bitmap (s);
-
- if (flipY)
- bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY);
-
- BitmapData data = bitmap.LockBits (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height),
- ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
-
- createTexture (data.Scan0, data.Width, data.Height);
-
- bitmap.UnlockBits (data);
-
- GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
- GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
- GL.GenerateMipmap (GenerateMipmapTarget.Texture2D);
-
- } catch (Exception ex) {
- Debug.WriteLine ("Error loading texture: " + Map + ":" + ex.Message);
- }
- }
- }
-
- public Texture(int width, int height)
- {
- createTexture (IntPtr.Zero, width, height);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp);
- }
-
- void createTexture(IntPtr data, int width, int height)
- {
- Width = width;
- Height = height;
-
- GL.GenTextures(1, out texRef);
- GL.BindTexture(TextureTarget.Texture2D, texRef);
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0,
- OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data);
- }
-
- public static implicit operator int(Texture t)
- {
- return t == null ? 0: t.texRef;
- }
- }
-
-}
+++ /dev/null
-//
-// vaoMesh.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-using System;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-
-namespace Crow
-{
- public class vaoMesh : IDisposable
- {
- public int vaoHandle,
- positionVboHandle,
- texVboHandle,
- eboHandle;
-
- public Vector3[] positions;
- public Vector2[] texCoords;
- public int[] indices;
-
- public vaoMesh()
- {
- }
-
- public vaoMesh (Vector3[] _positions, Vector2[] _texCoord, int[] _indices)
- {
- positions = _positions;
- texCoords = _texCoord;
- indices = _indices;
-
- CreateBuffers ();
- }
-
- public vaoMesh (float x, float y, float z, float width, float height, float TileX = 1f, float TileY = 1f)
- {
- positions =
- new Vector3[] {
- new Vector3 (x - width / 2, y + height / 2, z),
- new Vector3 (x - width / 2, y - height / 2, z),
- new Vector3 (x + width / 2, y + height / 2, z),
- new Vector3 (x + width / 2, y - height / 2, z)
- };
- texCoords = new Vector2[] {
- new Vector2 (0, TileY),
- new Vector2 (0, 0),
- new Vector2 (TileX, TileY),
- new Vector2 (TileX, 0)
- };
- indices = new int[] { 0, 1, 2, 3 };
-
- CreateBuffers ();
- }
- public static vaoMesh CreateCube(){
- vaoMesh tmp = new vaoMesh ();
- tmp.positions = new Vector3[]
- {
- new Vector3(-1.0f, -1.0f, -1.0f),
- new Vector3( -1.0f, -1.0f, 1.0f),
- new Vector3( 1.0f, -1.0f, -1.0f),
- new Vector3(1.0f, -1.0f, 1.0f),
- new Vector3(1.0f, 1.0f, -1.0f),
- new Vector3( 1.0f, 1.0f, 1.0f),
- new Vector3( -1.0f, 1.0f, -1.0f),
- new Vector3(-1.0f, 1.0f, 1.0f)
- };
- tmp.indices = new int[]
- {
- // front face
- 0, 2, 1, 1, 2, 3,
- // top face
- 2, 4, 3, 3, 4, 5,
- // back face
- 4, 6, 5, 5, 6, 7,
- // left face
- 6, 0, 7, 7, 0, 1,
- // bottom face
- 1, 3, 7, 7, 3, 5,
- // right face
-// 1, 5, 6, 6, 2, 1,
- };
- tmp.texCoords = new Vector2[]
- {
- new Vector2(0, 0),
- new Vector2(0, 1),
- new Vector2(1, 0),
- new Vector2(1, 1),
- new Vector2(0, 0),
- new Vector2(0, 1),
- new Vector2(1, 0),
- new Vector2(1, 1),
- };
- tmp.CreateBuffers ();
- return tmp;
-// Normals = new Vector3[]
-// {
-// new Vector3(-1.0f, -1.0f, 1.0f),
-// new Vector3( 1.0f, -1.0f, 1.0f),
-// new Vector3( 1.0f, 1.0f, 1.0f),
-// new Vector3(-1.0f, 1.0f, 1.0f),
-// new Vector3(-1.0f, -1.0f, -1.0f),
-// new Vector3( 1.0f, -1.0f, -1.0f),
-// new Vector3( 1.0f, 1.0f, -1.0f),
-// new Vector3(-1.0f, 1.0f, -1.0f),
-// };
-//
-// Colors = new int[]
-// {
-// Utilities.ColorToRgba32(Color.DarkRed),
-// Utilities.ColorToRgba32(Color.DarkRed),
-// Utilities.ColorToRgba32(Color.Gold),
-// Utilities.ColorToRgba32(Color.Gold),
-// Utilities.ColorToRgba32(Color.DarkRed),
-// Utilities.ColorToRgba32(Color.DarkRed),
-// Utilities.ColorToRgba32(Color.Gold),
-// Utilities.ColorToRgba32(Color.Gold),
-// };
- }
- public void CreateBuffers(){
- CreateVBOs ();
- CreateVAOs ();
- }
- protected void CreateVBOs()
- {
- positionVboHandle = GL.GenBuffer();
- GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
- GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
- new IntPtr(positions.Length * Vector3.SizeInBytes),
- positions, BufferUsageHint.StaticDraw);
-
- if (texCoords != null) {
- texVboHandle = GL.GenBuffer ();
- GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle);
- GL.BufferData<Vector2> (BufferTarget.ArrayBuffer,
- new IntPtr (texCoords.Length * Vector2.SizeInBytes),
- texCoords, BufferUsageHint.StaticDraw);
- }
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
-
- if (indices != null) {
- eboHandle = GL.GenBuffer ();
- GL.BindBuffer (BufferTarget.ElementArrayBuffer, eboHandle);
- GL.BufferData (BufferTarget.ElementArrayBuffer,
- new IntPtr (sizeof(uint) * indices.Length),
- indices, BufferUsageHint.StaticDraw);
- GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
- }
- }
- protected void CreateVAOs()
- {
- vaoHandle = GL.GenVertexArray();
- GL.BindVertexArray(vaoHandle);
-
- GL.EnableVertexAttribArray(0);
- GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
- GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
-
- if (texCoords != null) {
- GL.EnableVertexAttribArray (1);
- GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle);
- GL.VertexAttribPointer (1, 2, VertexAttribPointerType.Float, true, Vector2.SizeInBytes, 0);
- }
- if (indices != null)
- GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle);
-
- GL.BindVertexArray(0);
- }
-
- public void Render(BeginMode _primitiveType){
- GL.BindVertexArray(vaoHandle);
- if (indices == null)
- GL.DrawArrays (_primitiveType, 0, positions.Length);
- else
- GL.DrawElements(_primitiveType, indices.Length,
- DrawElementsType.UnsignedInt, IntPtr.Zero);
- GL.BindVertexArray (0);
- }
- public void Render(BeginMode _primitiveType, int[] _customIndices){
- GL.BindVertexArray(vaoHandle);
- GL.DrawElements(_primitiveType, _customIndices.Length,
- DrawElementsType.UnsignedInt, _customIndices);
- GL.BindVertexArray (0);
- }
- public void Render(BeginMode _primitiveType, int instances){
-
- GL.BindVertexArray(vaoHandle);
- GL.DrawElementsInstanced(_primitiveType, indices.Length,
- DrawElementsType.UnsignedInt, IntPtr.Zero, instances);
- GL.BindVertexArray (0);
- }
-
- #region IDisposable implementation
- public void Dispose ()
- {
- GL.DeleteBuffer (positionVboHandle);
- GL.DeleteBuffer (texVboHandle);
- GL.DeleteBuffer (eboHandle);
- GL.DeleteVertexArray (vaoHandle);
- }
- #endregion
-
- }
-}
\ No newline at end of file
+++ /dev/null
-//
-// OpenTKGameWindow.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-using System;
-using System.Threading;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-
-namespace Crow
-{
- public class OpenTKGameWindow : GameWindow, IValueChange
- {
- #region IValueChange implementation
- public event EventHandler<ValueChangeEventArgs> ValueChanged;
- public virtual void NotifyValueChanged(string MemberName, object _value)
- {
- if (ValueChanged != null)
- ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
- }
- #endregion
-
- public Interface CrowInterface;
-
- #region FPS
- int frameCpt = 0;
- int _fps = 0;
-
- public int fps {
- get { return _fps; }
- set {
- if (_fps == value)
- return;
-
- _fps = value;
-
- if (_fps > fpsMax) {
- fpsMax = _fps;
- ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax));
- } else if (_fps < fpsMin) {
- fpsMin = _fps;
- ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin));
- }
-
- ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps));
- #if MEASURE_TIME
- ValueChanged.Raise (this, new ValueChangeEventArgs ("update",
- this.CrowInterface.updateTime.ElapsedTicks.ToString () + " ticks"));
- ValueChanged.Raise (this, new ValueChangeEventArgs ("layouting",
- this.CrowInterface.layoutTime.ElapsedTicks.ToString () + " ticks"));
- ValueChanged.Raise (this, new ValueChangeEventArgs ("drawing",
- this.CrowInterface.drawingTime.ElapsedTicks.ToString () + " ticks"));
- ValueChanged.Raise (this, new ValueChangeEventArgs ("clipping",
- this.CrowInterface.clippingTime.ElapsedTicks.ToString () + " ticks"));
- #endif
- }
- }
-
- public int fpsMin = int.MaxValue;
- public int fpsMax = 0;
-
- void resetFps ()
- {
- fpsMin = int.MaxValue;
- fpsMax = 0;
- _fps = 0;
- }
- public string update = "";
- public string drawing = "";
- public string layouting = "";
- public string clipping = "";
- #endregion
-
- #region ctor
- public OpenTKGameWindow(int _width = 800, int _height = 600, string _title="Crow",
- int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
- int major=3, int minor=3)
- : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
- _title,GameWindowFlags.Default,DisplayDevice.Default,
- major,minor,OpenTK.Graphics.GraphicsContextFlags.Default)
- {
- }
- public OpenTKGameWindow (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags)
- : base(width,height,mode,title,options,device,major,minor,flags)
- {
- CrowInterface = new Interface ();
-
- Thread t = new Thread (interfaceThread);
- t.IsBackground = true;
- t.Start ();
- }
-
- #endregion
-
- void interfaceThread()
- {
- CrowInterface.Quit += Quit;
- CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
- while (CrowInterface.ClientRectangle.Size.Width == 0)
- Thread.Sleep (5);
-
- while (true) {
- CrowInterface.Update ();
- Thread.Sleep (1);
- }
- }
-
- public void Quit (object sender, EventArgs e)
- {
- this.Exit ();
- }
- void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
- {
- this.Cursor = new MouseCursor(
- (int)e.NewCursor.Xhot,
- (int)e.NewCursor.Yhot,
- (int)e.NewCursor.Width,
- (int)e.NewCursor.Height,
- e.NewCursor.data);
- }
-
- #region Events
- //those events are raised only if mouse isn't in a graphic object
- public event EventHandler<OpenTK.Input.MouseWheelEventArgs> MouseWheelChanged;
- public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonUp;
- public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonDown;
- public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseClick;
- public event EventHandler<OpenTK.Input.MouseMoveEventArgs> MouseMove;
- public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyDown;
- public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyUp;
-
- #endregion
-
- #region graphic context
- public int texID;
- public Shader shader;
- public vaoMesh quad;
- public Matrix4 projection;
-
- void createContext()
- {
- #region Create texture
- if (GL.IsTexture(texID))
- GL.DeleteTexture (texID);
- GL.GenTextures(1, out texID);
- GL.ActiveTexture (TextureUnit.Texture0);
- GL.BindTexture(TextureTarget.Texture2D, texID);
-
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
- ClientRectangle.Width, ClientRectangle.Height, 0,
- OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp);
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
- GL.BindTexture(TextureTarget.Texture2D, 0);
- #endregion
- }
- void OpenGLDraw()
- {
- bool blend, depthTest;
- GL.GetBoolean (GetPName.Blend, out blend);
- GL.GetBoolean (GetPName.DepthTest, out depthTest);
- GL.Enable (EnableCap.Blend);
- GL.Disable (EnableCap.DepthTest);
-
- shader.Enable ();
- shader.SetMVP (projection);
- GL.ActiveTexture (TextureUnit.Texture0);
- GL.BindTexture (TextureTarget.Texture2D, texID);
- lock (CrowInterface.RenderMutex) {
- if (CrowInterface.IsDirty) {
- GL.TexSubImage2D (TextureTarget.Texture2D, 0,
- CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
- CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
- OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp);
- CrowInterface.IsDirty = false;
- }
- }
- quad.Render (BeginMode.TriangleStrip);
- GL.BindTexture(TextureTarget.Texture2D, 0);
-
- if (!blend)
- GL.Disable (EnableCap.Blend);
- if (depthTest)
- GL.Enable (EnableCap.DepthTest);
- }
- #endregion
-
- /// <summary>
- /// Override this method for your OpenGL rendering calls
- /// </summary>
- public virtual void OnRender(FrameEventArgs e)
- {
- }
- /// <summary>
- /// Override this method to customize clear method between frames
- /// </summary>
- public virtual void GLClear()
- {
- GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
- }
-
- #region Game win overrides
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
-
- this.KeyPress += new EventHandler<OpenTK.KeyPressEventArgs>(OpenTKGameWindow_KeyPress);
- Keyboard.KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
- Keyboard.KeyUp += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyUp);
- Mouse.WheelChanged += new EventHandler<OpenTK.Input.MouseWheelEventArgs>(Mouse_WheelChanged);
- Mouse.ButtonDown += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(Mouse_ButtonDown);
- Mouse.ButtonUp += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(Mouse_ButtonUp);
- Mouse.Move += new EventHandler<OpenTK.Input.MouseMoveEventArgs>(Mouse_Move);
-
- GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- Console.WriteLine("\n\n*************************************");
- Console.WriteLine("GL version: " + GL.GetString (StringName.Version));
- Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor));
- Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion));
- Console.WriteLine("*************************************\n");
-
- projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1);
-
- shader = new Shader ();
- quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
- }
-
- protected override void OnUpdateFrame(FrameEventArgs e)
- {
- base.OnUpdateFrame(e);
- fps = (int)RenderFrequency;
-
-
- if (frameCpt > 50) {
- resetFps ();
- frameCpt = 0;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString());
- }
- frameCpt++;
- }
- protected override void OnRenderFrame(FrameEventArgs e)
- {
- GLClear ();
-
- base.OnRenderFrame(e);
-
- OnRender (e);
- OpenGLDraw ();
-
- SwapBuffers ();
- }
-
- protected override void OnResize(EventArgs e)
- {
- base.OnResize (e);
- CrowInterface.ProcessResize(
- new Rectangle(
- 0,
- 0,
- this.ClientRectangle.Width,
- this.ClientRectangle.Height));
- createContext ();
- GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height);
- }
- #endregion
-
- #region Mouse Handling
- void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){
- for (int i = 0; i < MouseState.MaxButtons; i++) {
- if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i))
- e.EnableBit (i);
- }
- }
- void Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e)
- {
- if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y))
- MouseMove.Raise (sender, otk_e);
- }
- void Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
- {
- if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button))
- MouseButtonUp.Raise (sender, otk_e);
- }
- void Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
- {
- if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button))
- MouseButtonDown.Raise (sender, otk_e);
- }
- void Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e)
- {
- if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise))
- MouseWheelChanged.Raise (sender, otk_e);
- }
- #endregion
-
- #region keyboard Handling
- void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
- {
- if (!CrowInterface.ProcessKeyDown((int)otk_e.Key))
- KeyboardKeyDown.Raise (this, otk_e);
- }
- void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
- {
- if (!CrowInterface.ProcessKeyUp((int)otk_e.Key))
- KeyboardKeyUp.Raise (this, otk_e);
- }
- void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e)
- {
- CrowInterface.ProcessKeyPress (e.KeyChar);
- }
- #endregion
- }
-}
--- /dev/null
+//
+// DrmKms.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+using Linux;
+using Linux.VT;
+using System.Text;
+
+namespace Crow
+{
+ public class Application : IDisposable
+ {
+ public enum RunState {
+ ActivateRequest,
+ DesactivateRequest,
+ Paused,
+ Running,
+ }
+ #if MEASURE_TIME
+ public List<PerformanceMeasure> PerfMeasures;
+ protected PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+ #endif
+
+ public bool Running = true;
+ public volatile RunState CurrentState = RunState.Running;
+
+ protected Interface CrowInterface;
+ protected DRI.DRIControler gpu;
+ protected Cairo.GLSurface cairoSurf { get { return gpu?.CairoSurf; }}
+
+ protected bool mouseIsInInterface = false;
+
+ protected volatile int ifaceSleep = 1, updateSleep = 0;
+
+ void interfaceThread()
+ {
+ while (CrowInterface.ClientRectangle.Size.Width == 0)
+ Thread.Sleep (5);
+
+ while (true) {
+ if (CurrentState == RunState.Running) {
+ CrowInterface.Update ();
+ Thread.Sleep (ifaceSleep);
+ } else
+ Thread.Sleep (1000);
+ }
+ }
+
+ int previousVT = -1, appVT = -1;
+
+ public Application(){
+ if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0)
+ throw new Exception ("signal handler registation failed");
+// if (Kernel.signal (Signal.SIGUSR2, switch_request_handle) < 0)
+// throw new Exception ("signal handler registation failed");
+ if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0)
+ throw new Exception ("SIGINT handler registation failed");
+
+ using (VTControler master = new VTControler ()) {
+ previousVT = master.CurrentVT;
+ appVT = master.FirstAvailableVT;
+
+ master.SwitchTo (appVT);
+
+ try {
+ master.KDMode = KDMode.GRAPHICS;
+// VT.vt_mode vtm = master.VTMode;
+// vtm.mode = VT.SwitchMode.PROCESS;
+// master.VTMode = vtm;
+ } catch (Exception ex) {
+ Console.WriteLine (ex.ToString ());
+ }
+ }
+
+ initDri ();
+
+ initCrow ();
+
+ initInput ();
+
+ MouseX = gpu.Width / 2;
+ MouseY = gpu.Height / 2;
+
+ initCursor ();
+ }
+
+ #region CROW
+ public GraphicObject Load (string path){
+ return CrowInterface.LoadInterface (path);
+ }
+
+ void initCrow () {
+ CrowInterface = new Interface ();
+
+ Thread t = new Thread (interfaceThread);
+ t.Name = "Interface";
+ t.IsBackground = true;
+ t.Start ();
+
+ CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height));
+ CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+
+ #if MEASURE_TIME
+ PerfMeasures = new List<PerformanceMeasure> (
+ new PerformanceMeasure[] {
+ this.CrowInterface.updateMeasure,
+ this.CrowInterface.layoutingMeasure,
+ this.CrowInterface.clippingMeasure,
+ this.CrowInterface.drawingMeasure,
+ this.glDrawMeasure
+ }
+ );
+ #endif
+ }
+ void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+ {
+ gpu.updateCursor (e.NewCursor);
+ }
+ #endregion
+
+ void initDri(){
+ gpu = new DRI.DRIControler();
+ //cairoSurf = gpu.CairoSurf;
+ }
+ void initCursor(){
+ gpu.updateCursor (XCursor.Default);
+ gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4);
+ }
+
+ void switch_request_handle (Signal s){
+ Console.WriteLine ("****** switch request catched: " + s.ToString());
+ using (VTControler master = new VTControler ()) {
+ Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
+ master.AcknoledgeSwitchRequest ();
+ }
+ }
+ void sigint_handler (Signal s){
+ Console.WriteLine ("{0}: SIGINT catched");
+ Running = false;
+ }
+
+ public virtual void Run ()
+ {
+ int cpt = 0;
+ while(Running){
+ switch (CurrentState) {
+ case RunState.ActivateRequest:
+ activate ();
+ continue;
+ case RunState.DesactivateRequest:
+ desactivate ();
+ continue;
+ case RunState.Paused:
+ Thread.Sleep (1000);
+ continue;
+ }
+
+ uiDraw ();
+
+ #if MEASURE_TIME
+ if (cpt%10==0){
+ foreach (PerformanceMeasure m in PerfMeasures)
+ m.NotifyChanges();
+ }
+ #endif
+
+ cpt++;
+ Thread.Sleep (updateSleep);
+ }
+ }
+ protected virtual void uiDraw (){
+// #if MEASURE_TIME
+// glDrawMeasure.StartCycle();
+// #endif
+
+ bool update = false;
+
+ if (updateMousePos) {
+ lock (Sync) {
+ updateMousePos = false;
+ gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4);
+ }
+ }
+
+ if (Monitor.TryEnter (CrowInterface.RenderMutex)) {
+ if (CrowInterface.IsDirty) {
+ CrowInterface.IsDirty = false;
+ update = true;
+ Rectangle r = CrowInterface.DirtyRect;
+ using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) {
+ using (Cairo.Surface d = new Cairo.ImageSurface (CrowInterface.dirtyBmp, Cairo.Format.ARGB32,
+ r.Width, r.Height, r.Width * 4)) {
+ ctx.SetSourceSurface (d, 0, 0);
+ ctx.Operator = Cairo.Operator.Source;
+ ctx.Paint ();
+ }
+ }
+ }
+ Monitor.Exit (CrowInterface.RenderMutex);
+ }
+
+// if (!update)
+// return;
+// update = false;
+
+
+
+
+ cairoSurf.Flush ();
+ cairoSurf.SwapBuffers ();
+
+ //gpu.UpdateWithPageFlip ();
+ gpu.Update();
+
+// #if MEASURE_TIME
+// glDrawMeasure.StopCycle ();
+// #endif
+ }
+
+ #region INPUT
+ Thread input_thread;
+ long exit;
+
+ static readonly object Sync = new object();
+ static readonly Crow.Key[] KeyMap = Evdev.KeyMap;
+ static long DeviceFDCount;
+
+ IntPtr udev;
+ IntPtr input_context;
+
+ int input_fd = 0;
+
+ InputInterface input_interface = new InputInterface(
+ OpenRestricted, CloseRestricted);
+ static CloseRestrictedCallback CloseRestricted = CloseRestrictedHandler;
+ static void CloseRestrictedHandler(int fd, IntPtr data)
+ {
+ Debug.Print("[Input] Closing fd {0}", fd);
+ int ret = Libc.close(fd);
+
+ if (ret < 0)
+ {
+ Debug.Print("[Input] Failed to close fd {0}. Error: {1}", fd, ret);
+ }
+ else
+ {
+ Interlocked.Decrement(ref DeviceFDCount);
+ }
+ }
+
+ static OpenRestrictedCallback OpenRestricted = OpenRestrictedHandler;
+ static int OpenRestrictedHandler(IntPtr path, int flags, IntPtr data)
+ {
+ int fd = Libc.open(path, (OpenFlags)flags);
+ Debug.Print("[Input] Opening '{0}' with flags {1}. fd:{2}",
+ Marshal.PtrToStringAnsi(path), (OpenFlags)flags, fd);
+
+ if (fd >= 0)
+ {
+ Interlocked.Increment(ref DeviceFDCount);
+ }
+
+ return fd;
+ }
+
+ void initInput (){
+ Semaphore ready = new Semaphore(0, 1);
+ input_thread = new Thread (InputThreadLoop);
+ input_thread.Name = "input_thread";
+ input_thread.IsBackground = true;
+ input_thread.Start(ready);
+ }
+
+ void InputThreadLoop(object semaphore)
+ {
+ Debug.Print("[Input] Running on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ Setup();
+
+ // Inform the parent thread that initialization has completed successfully
+ (semaphore as Semaphore).Release();
+ Debug.Print("[Input] Released main thread.", input_context);
+
+ // Use a blocking poll for input messages, in order to reduce CPU usage
+ PollFD poll_fd = new PollFD();
+ poll_fd.fd = input_fd;
+ poll_fd.events = PollFlags.In;
+ Debug.Print("[Input] Created PollFD({0}, {1})", poll_fd.fd, poll_fd.events);
+
+ Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events);
+ while (Interlocked.Read(ref exit) == 0)
+ {
+ if (CurrentState != RunState.Running) {
+ Thread.Sleep (1000);
+ continue;
+ }
+ //drmTimeOut.Restart ();
+
+ int ret = Libc.poll(ref poll_fd, 1, -1);
+ ErrorNumber error = (ErrorNumber)Marshal.GetLastWin32Error();
+ bool is_error =
+ ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
+ (poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
+
+ if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
+ ProcessEvents(input_context);
+
+ if (is_error)
+ {
+ Debug.Print("[Input] Exiting input loop {0} due to poll error [ret:{1} events:{2}]. Error: {3}.",
+ input_thread.ManagedThreadId, ret, poll_fd.revents, error);
+ Interlocked.Increment(ref exit);
+ }
+ }
+ Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
+ }
+
+ void Setup()
+ {
+ // Todo: add static path fallback when udev is not installed.
+ udev = Udev.New();
+ if (udev == IntPtr.Zero)
+ {
+ Debug.Print("[Input] Udev.New() failed.");
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] Udev.New() = {0:x}", udev);
+
+ input_context = LibInput.CreateContext(input_interface, IntPtr.Zero, udev);
+ if (input_context == IntPtr.Zero)
+ {
+ Debug.Print("[Input] LibInput.CreateContext({0:x}) failed.", udev);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.CreateContext({0:x}) = {1:x}", udev, input_context);
+
+ string seat_id = "seat0";
+ int seat_assignment = LibInput.AssignSeat(input_context, seat_id);
+ if (seat_assignment == -1)
+ {
+ Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1} failed.", input_context, seat_id);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1}", input_context, seat_id);
+
+ input_fd = LibInput.GetFD(input_context);
+ if (input_fd < 0)
+ {
+ Debug.Print("[Input] LibInput.GetFD({0:x}) failed.", input_context);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.GetFD({0:x}) = {1}.", input_context, input_fd);
+
+ ProcessEvents(input_context);
+ LibInput.Resume(input_context);
+ Debug.Print("[Input] LibInput.Resume({0:x})", input_context);
+
+ if (Interlocked.Read(ref DeviceFDCount) <= 0)
+ {
+ Debug.Print("[Error] Failed to open any input devices.");
+ Debug.Print("[Error] Ensure that you have access to '/dev/input/event*'.");
+ Interlocked.Increment(ref exit);
+ }
+ }
+
+ void ProcessEvents(IntPtr input_context)
+ {
+ // Process all events in the event queue
+ while (true)
+ {
+ // Data available
+ int ret = LibInput.Dispatch(input_context);
+ if (ret != 0)
+ {
+ Debug.Print("[Input] LibInput.Dispatch({0:x}) failed. Error: {1}",
+ input_context, ret);
+ break;
+ }
+
+ IntPtr pevent = LibInput.GetEvent(input_context);
+ if (pevent == IntPtr.Zero)
+ {
+ break;
+ }
+
+ IntPtr device = LibInput.GetDevice(pevent);
+ InputEventType type = LibInput.GetEventType(pevent);
+
+ lock (Sync)
+ {
+ switch (type)
+ {
+ // case InputEventType.DeviceAdded:
+ // HandleDeviceAdded(input_context, device);
+ // break;
+ //
+ // case InputEventType.DeviceRemoved:
+ // HandleDeviceRemoved(input_context, device);
+ // break;
+ //
+ case InputEventType.KeyboardKey:
+ //run = false;
+ handleKeyboard(LibInput.GetKeyboardEvent(pevent));
+ break;
+ //
+ case InputEventType.PointerAxis:
+ handlePointerAxis(LibInput.GetPointerEvent(pevent));
+ break;
+
+ case InputEventType.PointerButton:
+ handlePointerButton (LibInput.GetPointerEvent(pevent));
+ break;
+
+ case InputEventType.PointerMotion:
+ handlePointerMotion (LibInput.GetPointerEvent(pevent));
+ break;
+
+// case InputEventType.PointerMotionAbsolute:
+// handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent));
+// break;
+ }
+ }
+
+ LibInput.DestroyEvent(pevent);
+ }
+ }
+ int MouseX = 0, MouseY = 0;
+ volatile bool updateMousePos = true;
+
+ int roundDelta (double d){
+ return d > 0 ? (int)Math.Ceiling(d) : (int)Math.Floor (d);
+ }
+ void handlePointerAxis(PointerEvent e){
+// if (e.HasAxis(PointerAxis.HorizontalScroll))
+// {
+// CrowInterface.ProcessMouseWheelChanged ((float)e.AxisValue (PointerAxis.HorizontalScroll));
+// }
+ if (e.HasAxis(PointerAxis.VerticalScroll))
+ {
+ CrowInterface.ProcessMouseWheelChanged ((float)-e.AxisValue (PointerAxis.VerticalScroll));
+ }
+ }
+ void handlePointerMotion(PointerEvent e)
+ {
+ MouseX += roundDelta (e.DeltaX);
+ MouseY += roundDelta (e.DeltaY);
+
+ Rectangle bounds = CrowInterface.ClientRectangle;
+ if (MouseX < bounds.Left)
+ MouseX = bounds.Left;
+ else if (MouseX > bounds.Right)
+ MouseX = bounds.Right;
+
+ if (MouseY < bounds.Top)
+ MouseY = bounds.Top;
+ else if (MouseY > bounds.Bottom)
+ MouseY = bounds.Bottom;
+
+ CrowInterface.ProcessMouseMove (MouseX, MouseY);
+
+ updateMousePos = true;
+ }
+ void handlePointerButton (PointerEvent e)
+ {
+ int but = 0;
+ switch (e.Button) {
+ case EvdevButton.LEFT:
+ but = 0;
+ break;
+ case EvdevButton.MIDDLE:
+ but = 1;
+ break;
+ case EvdevButton.RIGHT:
+ but = 2;
+ break;
+ }
+ if (e.ButtonState == global::Linux.ButtonState.Pressed)
+ CrowInterface.ProcessMouseButtonDown (but);
+ else
+ CrowInterface.ProcessMouseButtonUp (but);
+ }
+
+ KeyModifiers curModifiers = KeyModifiers.None;
+
+ void handleKeyboard(KeyboardEvent e)
+ {
+ int key = (int)Evdev.KeyMap [e.Key];
+ Key k = (Key)key;
+ if (e.KeyState == KeyState.Pressed) {
+ CrowInterface.ProcessKeyDown (key);
+ switch (k) {
+ case Key.ShiftLeft:
+ case Key.ShiftRight:
+ curModifiers |= KeyModifiers.Shift;
+ break;
+ case Key.ControlLeft:
+ case Key.ControlRight:
+ curModifiers |= KeyModifiers.Control;
+ break;
+ case Key.AltLeft:
+ curModifiers |= KeyModifiers.Alt;
+ break;
+ case Key.AltRight:
+ curModifiers |= KeyModifiers.AltGr;
+ break;
+ }
+ }else {
+ CrowInterface.ProcessKeyUp (key);
+ switch (k) {
+ case Key.ShiftLeft:
+ case Key.ShiftRight:
+ curModifiers &= ~KeyModifiers.Shift;
+ break;
+ case Key.ControlLeft:
+ case Key.ControlRight:
+ curModifiers &= ~KeyModifiers.Control;
+ break;
+ case Key.AltLeft:
+ curModifiers &= ~KeyModifiers.Alt;
+ break;
+ case Key.AltRight:
+ curModifiers &= ~KeyModifiers.AltGr;
+ break;
+ }
+// if (!keymap.ContainsKey (curModifiers)) {
+// Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers);
+// return;
+// }
+ // string tmp = keymap [curModifiers] [e.Key];
+ // if (string.IsNullOrEmpty (tmp))
+ // return;
+ // if (char.IsControl (tmp[0]))
+ // return;
+ // CrowInterface.ProcessKeyPress (tmp [0]);
+ }
+ }
+
+ #endregion
+
+
+
+ void desactivate () {
+ CurrentState = RunState.Paused;
+
+ //cairoSurf = null;
+ gpu.Dispose ();
+ gpu = null;
+ }
+ void activate (){
+ initDri();
+ initCursor ();
+
+ CurrentState = RunState.Running;
+ }
+
+ #region IDisposable implementation
+ ~Application(){
+ Dispose (false);
+ }
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ protected virtual void Dispose (bool disposing){
+ if (gpu != null)
+ gpu.Dispose ();
+ gpu = null;
+
+ using (VTControler master = new VTControler ()) {
+ // try {
+ // master.KDMode = VT.KDMode.TEXT;
+ // } catch (Exception ex) {
+ // Console.WriteLine (ex.ToString ());
+ // }
+ master.SwitchTo (previousVT);
+ }
+
+ }
+ #endregion
+ }
+}
+
--- /dev/null
+#region License
+//
+// Evdev.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014
+//
+// 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.
+//
+using Linux;
+using Crow;
+
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Linux
+{
+ // Bindings for linux/input.h
+ class Evdev
+ {
+ public const int KeyCount = 0x300;
+ public const int AxisCount = 0x40;
+ public const int EventCount = (int)EvdevType.CNT;
+
+ #region KeyMap
+
+ public static readonly Key[] KeyMap = new Key[]
+ {
+ // 0-7
+ Key.Unknown,
+ Key.Escape,
+ Key.Number1,
+ Key.Number2,
+ Key.Number3,
+ Key.Number4,
+ Key.Number5,
+ Key.Number6,
+ // 8-15
+ Key.Number7,
+ Key.Number8,
+ Key.Number9,
+ Key.Number0,
+ Key.Minus,
+ Key.Plus,
+ Key.BackSpace,
+ Key.Tab,
+ // 16-23
+ Key.Q,
+ Key.W,
+ Key.E,
+ Key.R,
+ Key.T,
+ Key.Y,
+ Key.U,
+ Key.I,
+ // 24-31
+ Key.O,
+ Key.P,
+ Key.BracketLeft,
+ Key.BracketRight,
+ Key.Enter,
+ Key.ControlLeft,
+ Key.A,
+ Key.S,
+ // 32-39
+ Key.D,
+ Key.F,
+ Key.G,
+ Key.H,
+ Key.J,
+ Key.K,
+ Key.L,
+ Key.Semicolon,
+ // 40-47
+ Key.Quote,
+ Key.Tilde,
+ Key.ShiftLeft,
+ Key.BackSlash, //Key.Execute,
+ Key.Z,
+ Key.X,
+ Key.C,
+ Key.V, //Key.Help,
+ // 48-55
+ Key.B,
+ Key.N,
+ Key.M,
+ Key.Comma,
+ Key.Period,
+ Key.Slash,
+ Key.ShiftRight,
+ Key.KeypadMultiply,
+ // 56-63
+ Key.AltLeft,
+ Key.Space,
+ Key.CapsLock,
+ Key.F1,
+ Key.F2,
+ Key.F3,
+ Key.F4,
+ Key.F5,
+ // 64-71
+ Key.F6,
+ Key.F7,
+ Key.F8,
+ Key.F9,
+ Key.F10,
+ Key.NumLock,
+ Key.ScrollLock,
+ Key.Keypad7,
+ // 72-79
+ Key.Keypad8,
+ Key.Keypad9,
+ Key.KeypadSubtract,
+ Key.Keypad4,
+ Key.Keypad5,
+ Key.Keypad6,
+ Key.KeypadPlus,
+ Key.Keypad1,
+ // 80-87
+ Key.Keypad2,
+ Key.Keypad3,
+ Key.Keypad0,
+ Key.KeypadPeriod,
+ Key.Unknown,
+ Key.Unknown, // zenkakuhankaku
+ Key.Unknown, // 102ND
+ Key.F11,
+ // 88-95
+ Key.F12,
+ Key.Unknown, // ro
+ Key.Unknown, // katakana
+ Key.Unknown, // hiragana
+ Key.Unknown, // henkan
+ Key.Unknown, // katakanahiragana
+ Key.Unknown, // muhenkan
+ Key.Unknown, // kpjpcomma
+ // 96-103
+ Key.KeypadEnter,
+ Key.ControlRight,
+ Key.KeypadDivide,
+ Key.Unknown, // sysrq
+ Key.AltRight,
+ Key.Unknown, // linefeed
+ Key.Home,
+ Key.Up,
+ // 104-111
+ Key.PageUp,
+ Key.Left,
+ Key.Right,
+ Key.End,
+ Key.Down,
+ Key.PageDown,
+ Key.Insert,
+ Key.Delete,
+ // 112-119
+ Key.Unknown, // macro
+ Key.Unknown, // mute
+ Key.Unknown, // volumedown
+ Key.Unknown, // volumeup
+ Key.Unknown, // power
+ Key.Unknown, // kpequal
+ Key.Unknown, // kpplusminus
+ Key.Pause,
+ // 120-127
+ Key.Unknown, // scale
+ Key.Unknown, // kpcomma
+ Key.Unknown, // hangeul / hanguel
+ Key.Unknown, // hanja
+ Key.Unknown, // yen
+ Key.WinLeft,
+ Key.WinRight,
+ Key.Unknown, // compose
+ // 128-135
+ Key.Unknown, // stop
+ Key.Unknown, // again
+ Key.Unknown, // props
+ Key.Unknown, // undo
+ Key.Unknown, // front
+ Key.Unknown, // copy
+ Key.Unknown, // open
+ Key.Unknown, // paste
+ // 136-143
+ Key.Unknown, // find
+ Key.Unknown, // cut
+ Key.Unknown, // help
+ Key.Unknown, // menu
+ Key.Unknown, // calc
+ Key.Unknown, // setup
+ Key.Unknown, // sleep
+ Key.Unknown, // wakeup
+ // 144-151
+ Key.Unknown, // file
+ Key.Unknown, // send file
+ Key.Unknown, // delete file
+ Key.Unknown, // xfer
+ Key.Unknown, // prog1
+ Key.Unknown, // prog2
+ Key.Unknown, // www
+ Key.Unknown, // msdos
+ // 152-159
+ Key.Unknown, // coffee / screenlock
+ Key.Unknown, // direction
+ Key.Unknown, // cycle windows
+ Key.Unknown, // mail
+ Key.Unknown, // bookmarks
+ Key.Unknown, // computer
+ Key.Back,
+ Key.Unknown, // forward
+ // 160-167
+ Key.Unknown, // close cd
+ Key.Unknown, // eject cd
+ Key.Unknown, // eject/close cd
+ Key.Unknown, // next song
+ Key.Unknown, // play/pause
+ Key.Unknown, // previous song
+ Key.Unknown, // stop cd
+ Key.Unknown, // record
+ // 168-175
+ Key.Unknown, // rewind
+ Key.Unknown, // phone
+ Key.Unknown, // iso
+ Key.Unknown, // config
+ Key.Unknown, // homepage
+ Key.Unknown, // refresh
+ Key.Unknown, // exit
+ Key.Unknown, // move,
+ // 176-183
+ Key.Unknown, // edit,
+ Key.Unknown, // scroll up,
+ Key.Unknown, // scroll down,
+ Key.Unknown, // kp left paren,
+ Key.Unknown, // kp right paren,
+ Key.Unknown, // new,
+ Key.Unknown, // redo,
+ Key.F13,
+ // 184-191
+ Key.F14,
+ Key.F15,
+ Key.F16,
+ Key.F17,
+ Key.F18,
+ Key.F19,
+ Key.F20,
+ Key.F21,
+ // 192-199
+ Key.F22,
+ Key.F23,
+ Key.F24,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ // 200-207
+ Key.Unknown, // play cd
+ Key.Unknown, // pause cd
+ Key.Unknown, // prog3
+ Key.Unknown, // prog4
+ Key.Unknown, // dashboard
+ Key.Unknown, // suspend
+ Key.Unknown, // close
+ Key.Unknown, // play
+ // 208-215
+ Key.Unknown, // fast forward
+ Key.Unknown, // bass boost
+ Key.Unknown, // print
+ Key.Unknown, // hp
+ Key.Unknown, // camera
+ Key.Unknown, // sound
+ Key.Unknown, // question
+ Key.Unknown, // email
+ // 216-223
+ Key.Unknown, // chat
+ Key.Unknown, // search
+ Key.Unknown, // connect
+ Key.Unknown, // finance
+ Key.Unknown, // sport
+ Key.Unknown, // shop
+ Key.Unknown, // alt erase
+ Key.Unknown, // cancel
+ // 224-231
+ Key.Unknown, // brightness down
+ Key.Unknown, // brightness up
+ Key.Unknown, // media
+ Key.Unknown, // switch video mode
+ Key.Unknown, // dillum toggle
+ Key.Unknown, // dillum down
+ Key.Unknown, // dillum up
+ Key.Unknown, // send
+ // 232-239
+ Key.Unknown, // reply
+ Key.Unknown, // forward email
+ Key.Unknown, // save
+ Key.Unknown, // documents
+ Key.Unknown, // battery
+ Key.Unknown, // bluetooth
+ Key.Unknown, // wlan
+ Key.Unknown, // uwb
+ // 240-247
+ Key.Unknown,
+ Key.Unknown, // video next
+ Key.Unknown, // video prev
+ Key.Unknown, // brightness cycle
+ Key.Unknown, // brightness zero
+ Key.Unknown, // display off
+ Key.Unknown, // wwan / wimax
+ Key.Unknown, // rfkill
+ // 248-255
+ Key.Unknown, // mic mute
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown, // reserved
+ };
+
+ #endregion
+
+ public static MouseButton GetMouseButton(EvdevButton button)
+ {
+ switch (button)
+ {
+ case EvdevButton.LEFT:
+ return MouseButton.Left;
+ case EvdevButton.RIGHT:
+ return MouseButton.Right;
+ case EvdevButton.MIDDLE:
+ return MouseButton.Middle;
+ case EvdevButton.BTN0:
+ return MouseButton.Button1;
+ case EvdevButton.BTN1:
+ return MouseButton.Button2;
+ case EvdevButton.BTN2:
+ return MouseButton.Button3;
+ case EvdevButton.BTN3:
+ return MouseButton.Button4;
+ case EvdevButton.BTN4:
+ return MouseButton.Button5;
+ case EvdevButton.BTN5:
+ return MouseButton.Button6;
+ case EvdevButton.BTN6:
+ return MouseButton.Button7;
+ case EvdevButton.BTN7:
+ return MouseButton.Button8;
+ case EvdevButton.BTN8:
+ return MouseButton.Button9;
+ default:
+ Debug.Print("[Input] Unknown EvdevButton {0}", button);
+ return MouseButton.Left;
+ }
+ }
+
+ static uint IOCreate(DirectionFlags dir, int number, int length)
+ {
+ long v =
+ ((byte)dir << 30) |
+ ((byte)'E' << 8) |
+ (number << 0) |
+ (length << 16);
+ return (uint)v;
+ }
+
+ // Get absolute value / limits
+ public static int GetAbs(int fd, EvdevAxis axis, out InputAbsInfo info)
+ {
+ info = default(InputAbsInfo);
+ unsafe
+ {
+ fixed (InputAbsInfo* pinfo = &info)
+ {
+ // EVIOCGABS(abs) = _IOR('E', 0x40 + (abs), struct input_absinfo)
+ uint ioctl = IOCreate(DirectionFlags.Read, (int)axis + 0x40, BlittableValueType<InputAbsInfo>.Stride);
+ int retval = Libc.ioctl(fd, ioctl, new IntPtr(pinfo));
+ return retval;
+ }
+ }
+ }
+
+ // Get supported event bits
+ public static int GetBit(int fd, EvdevType ev, int length, IntPtr data)
+ {
+ // EVIOCGBIT = _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
+ uint ioctl = IOCreate(DirectionFlags.Read, (int)ev + 0x20, length);
+ int retval = Libc.ioctl(fd, ioctl, data);
+ return retval;
+ }
+
+ public static int GetName(int fd, out string name)
+ {
+ unsafe
+ {
+ sbyte* pname = stackalloc sbyte[129];
+ int ret = Libc.ioctl(fd, (uint)EvdevIoctl.Name128, new IntPtr(pname));
+ name = new string(pname);
+ return ret;
+ }
+ }
+
+ public static int GetId(int fd, out EvdevInputId id)
+ {
+ id = default(EvdevInputId);
+ unsafe
+ {
+ fixed (EvdevInputId* pid = &id)
+ {
+ return Libc.ioctl(fd, (uint)EvdevIoctl.Id, new IntPtr(pid));
+ }
+ }
+ }
+ }
+
+ enum EvdevAxis
+ {
+ X = 0x00,
+ Y = 0x01,
+ Z = 0x02,
+ RX = 0x03,
+ RY = 0x04,
+ RZ = 0x05,
+ THROTTLE = 0x06,
+ RUDDER = 0x07,
+ WHEEL = 0x08,
+ GAS = 0x09,
+ BRAKE = 0x0a,
+ HAT0X = 0x10,
+ HAT0Y = 0x11,
+ HAT1X = 0x12,
+ HAT1Y = 0x13,
+ HAT2X = 0x14,
+ HAT2Y = 0x15,
+ HAT3X = 0x16,
+ HAT3Y = 0x17,
+ PRESSURE = 0x18,
+ DISTANCE = 0x19,
+ TILT_X = 0x1a,
+ TILT_Y = 0x1b,
+ TOOL_WIDTH = 0x1c,
+
+ VOLUME = 0x20,
+
+ MISC = 0x28,
+
+ MT_SLOT = 0x2f, /* MT slot being modified */
+ MT_TOUCH_MAJOR = 0x30, /* Major axis of touching ellipse */
+ MT_TOUCH_MINOR = 0x31, /* Minor axis (omit if circular) */
+ MT_WIDTH_MAJOR = 0x32, /* Major axis of approaching ellipse */
+ MT_WIDTH_MINOR = 0x33, /* Minor axis (omit if circular) */
+ MT_ORIENTATION = 0x34, /* Ellipse orientation */
+ MT_POSITION_X = 0x35, /* Center X touch position */
+ MT_POSITION_Y = 0x36, /* Center Y touch position */
+ MT_TOOL_TYPE = 0x37, /* Type of touching device */
+ MT_BLOB_ID = 0x38, /* Group a set of packets as a blob */
+ MT_TRACKING_ID = 0x39, /* Unique ID of initiated contact */
+ MT_PRESSURE = 0x3a, /* Pressure on contact area */
+ MT_DISTANCE = 0x3b, /* Contact hover distance */
+ MT_TOOL_X = 0x3c, /* Center X tool position */
+ MT_TOOL_Y = 0x3d, /* Center Y tool position */
+
+ MAX = 0x3f,
+ CNT = (MAX+1),
+ }
+
+ enum EvdevButton
+ {
+ MISC = 0x100,
+ BTN0 = 0x100,
+ BTN1 = 0x101,
+ BTN2 = 0x102,
+ BTN3 = 0x103,
+ BTN4 = 0x104,
+ BTN5 = 0x105,
+ BTN6 = 0x106,
+ BTN7 = 0x107,
+ BTN8 = 0x108,
+ BTN9 = 0x109,
+
+ MOUSE = 0x110,
+ LEFT = 0x110,
+ RIGHT = 0x111,
+ MIDDLE = 0x112,
+ SIDE = 0x113,
+ EXTRA = 0x114,
+ FORWARD = 0x115,
+ BACK = 0x116,
+ TASK = 0x117,
+
+ JOYSTICK = 0x120,
+ TRIGGER = 0x120,
+ THUMB = 0x121,
+ THUMB2 = 0x122,
+ TOP = 0x123,
+ TOP2 = 0x124,
+ PINKIE = 0x125,
+ BASE = 0x126,
+ BASE2 = 0x127,
+ BASE3 = 0x128,
+ BASE4 = 0x129,
+ BASE5 = 0x12a,
+ BASE6 = 0x12b,
+ DEAD = 0x12f,
+
+ GAMEPAD = 0x130,
+ SOUTH = 0x130,
+ A = SOUTH,
+ EAST = 0x131,
+ B = EAST,
+ C = 0x132,
+ NORTH = 0x133,
+ X = NORTH,
+ WEST = 0x134,
+ Y = WEST,
+ Z = 0x135,
+ TL = 0x136,
+ TR = 0x137,
+ TL2 = 0x138,
+ TR2 = 0x139,
+ SELECT = 0x13a,
+ START = 0x13b,
+ MODE = 0x13c,
+ THUMBL = 0x13d,
+ THUMBR = 0x13e,
+
+ DIGI = 0x140,
+ TOOL_PEN = 0x140,
+ TOOL_RUBBER = 0x141,
+ TOOL_BRUSH = 0x142,
+ TOOL_PENCIL = 0x143,
+ TOOL_AIRBRUSH = 0x144,
+ TOOL_FINGER = 0x145,
+ TOOL_MOUSE = 0x146,
+ TOOL_LENS = 0x147,
+ TOOL_QUINTTAP = 0x148, // Five fingers on trackpad
+ TOUCH = 0x14a,
+ STYLUS = 0x14b,
+ STYLUS2 = 0x14c,
+ TOOL_DOUBLETAP = 0x14d,
+ TOOL_TRIPLETAP = 0x14e,
+ TOOL_QUADTAP = 0x14f, // Four fingers on trackpad
+
+ WHEEL = 0x150,
+ GEAR_DOWN = 0x150,
+ GEAR_UP = 0x151,
+
+ DPAD_UP = 0x220,
+ DPAD_DOWN = 0x221,
+ DPAD_LEFT = 0x222,
+ DPAD_RIGHT = 0x223,
+
+ Last = 0x300,
+ }
+
+ enum EvdevType : byte
+ {
+ SYN = 0x00,
+ KEY = 0x01,
+ REL = 0x02,
+ ABS = 0x03,
+ MSC = 0x04,
+ SW = 0x05,
+ LED = 0x11,
+ SND = 0x12,
+ REP = 0x14,
+ FF = 0x15,
+ PWR = 0x16,
+ FF_STATUS = 0x17,
+ MAX = 0x1f,
+ CNT = (MAX+1),
+ }
+
+ enum EvdevIoctl : uint
+ {
+ Id = (2u << 30) | ((byte)'E' << 8) | (0x02u << 0) | (8u << 16), //EVIOCGID = _IOR('E', 0x02, struct input_id)
+ Name128 = (2u << 30) | ((byte)'E' << 8) | (0x06u << 0) | (128u << 16), //EVIOCGNAME(len) = _IOC(_IOC_READ, 'E', 0x06, len)
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputAbsInfo
+ {
+ public int Value;
+ public int Minimum;
+ public int Maximum;
+ public int Fuzz;
+ public int Flat;
+ public int Resolution;
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputId
+ {
+ public ushort BusType;
+ public ushort Vendor;
+ public ushort Product;
+ public ushort Version;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputEvent
+ {
+ public TimeVal Time;
+ ushort type;
+ public ushort Code;
+ public int Value;
+
+ public EvdevType Type { get { return (EvdevType)type; } }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct TimeVal
+ {
+ public IntPtr Seconds;
+ public IntPtr MicroSeconds;
+ }
+}
+
--- /dev/null
+#region License
+//
+// LibInput.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// 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
+
+#pragma warning disable 0169, 0219
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Linux
+{
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ delegate int OpenRestrictedCallback(IntPtr path, int flags, IntPtr data);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ delegate void CloseRestrictedCallback(int fd, IntPtr data);
+
+ class LibInput
+ {
+ internal const string lib = "libinput";
+
+ [DllImport(lib, EntryPoint = "libinput_udev_create_context", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr CreateContext(InputInterface @interface,
+ IntPtr user_data, IntPtr udev);
+
+ [DllImport(lib, EntryPoint = "libinput_udev_assign_seat", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int AssignSeat(IntPtr libinput, string seat_id);
+
+ [DllImport(lib, EntryPoint = "libinput_destroy", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void DestroyContext(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_event_destroy", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void DestroyEvent(IntPtr @event);
+
+ [DllImport(lib, EntryPoint = "libinput_device_get_sysname", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr DeviceGetNameInternal(IntPtr device);
+ public static string DeviceGetName(IntPtr device)
+ {
+ unsafe
+ {
+ return new string((sbyte*)DeviceGetNameInternal(device));
+ }
+ }
+
+ [DllImport(lib, EntryPoint = "libinput_device_get_user_data", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr DeviceGetData(IntPtr device);
+
+ [DllImport(lib, EntryPoint = "libinput_device_set_user_data", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void DeviceSetData(IntPtr device, IntPtr user_data);
+
+ [DllImport(lib, EntryPoint = "libinput_device_get_output_name", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr DeviceGetOutputNameInternal(IntPtr device);
+ public static string DeviceGetOutputName(IntPtr device)
+ {
+ unsafe
+ {
+ sbyte* pname = (sbyte*)DeviceGetOutputNameInternal(device);
+ return pname == null ? String.Empty : new string(pname);
+ }
+ }
+
+ [DllImport(lib, EntryPoint = "libinput_device_get_seat", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr DeviceGetSeat(IntPtr device);
+
+ [DllImport(lib, EntryPoint = "libinput_device_has_capability", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool DeviceHasCapability(IntPtr device, DeviceCapability capability);
+
+ [DllImport(lib, EntryPoint = "libinput_dispatch", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int Dispatch(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_event_get_device", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr GetDevice(IntPtr @event);
+
+ [DllImport(lib, EntryPoint = "libinput_get_event", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr GetEvent(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_event_get_keyboard_event", CallingConvention = CallingConvention.Cdecl)]
+ public static extern KeyboardEvent GetKeyboardEvent(IntPtr @event);
+
+ [DllImport(lib, EntryPoint = "libinput_event_get_pointer_event", CallingConvention = CallingConvention.Cdecl)]
+ public static extern PointerEvent GetPointerEvent(IntPtr @event);
+
+ [DllImport(lib, EntryPoint = "libinput_event_get_type", CallingConvention = CallingConvention.Cdecl)]
+ public static extern InputEventType GetEventType(IntPtr @event);
+
+ [DllImport(lib, EntryPoint = "libinput_get_fd", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int GetFD(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_next_event_type", CallingConvention = CallingConvention.Cdecl)]
+ public static extern InputEventType NextEventType(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_resume", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void Resume(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_suspend", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void Suspend(IntPtr libinput);
+
+ [DllImport(lib, EntryPoint = "libinput_seat_get_logical_name", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr SeatGetLogicalNameInternal(IntPtr seat);
+ public static string SeatGetLogicalName(IntPtr seat)
+ {
+ unsafe
+ {
+ return new string((sbyte*)SeatGetLogicalNameInternal(seat));
+ }
+ }
+
+ [DllImport(lib, EntryPoint = "libinput_seat_get_physical_name", CallingConvention = CallingConvention.Cdecl)]
+ static extern public IntPtr SeatGetPhysicalNameInternal(IntPtr seat);
+ public static string SeatGetPhysicalName(IntPtr seat)
+ {
+ unsafe
+ {
+ return new string((sbyte*)SeatGetPhysicalNameInternal(seat));
+ }
+ }
+ }
+
+ enum DeviceCapability
+ {
+ Keyboard = 0,
+ Mouse,
+ Touch
+ }
+
+ enum InputEventType
+ {
+ None = 0,
+
+ DeviceAdded,
+ DeviceRemoved,
+
+ KeyboardKey = 300,
+
+ PointerMotion = 400,
+ PointerMotionAbsolute,
+ PointerButton,
+ PointerAxis,
+
+ TouchDown = 500,
+ TouchUP,
+ TouchMotion,
+ TouchCancel,
+
+ /// \internal
+ /// <summary>
+ /// Signals the end of a set of touchpoints at one device sample
+ /// time. This event has no coordinate information attached.
+ /// </summary>
+ TouchFrame
+ }
+
+ enum ButtonState
+ {
+ Released = 0,
+ Pressed = 1
+ }
+
+ enum KeyState
+ {
+ Released = 0,
+ Pressed = 1
+ }
+
+ enum PointerAxis
+ {
+ VerticalScroll = 0,
+ HorizontalScroll = 1
+ }
+
+ struct Fixed24
+ {
+ internal readonly int Value;
+
+ public static implicit operator double(Fixed24 n)
+ {
+ long l = ((1023L + 44L) << 52) + (1L << 51) + n.Value;
+ unsafe
+ {
+ double d = *(double*)&l;
+ return d - (3L << 43);
+ }
+ }
+
+ public static implicit operator float(Fixed24 n)
+ {
+ return (float)(double)n;
+ }
+
+ public static explicit operator int(Fixed24 n)
+ {
+ return n.Value >> 8;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ class InputInterface
+ {
+ internal readonly IntPtr open;
+ internal readonly IntPtr close;
+
+ public InputInterface(
+ OpenRestrictedCallback open_restricted,
+ CloseRestrictedCallback close_restricted)
+ {
+ if (open_restricted == null || close_restricted == null)
+ throw new ArgumentNullException();
+
+ open = Marshal.GetFunctionPointerForDelegate(open_restricted);
+ close = Marshal.GetFunctionPointerForDelegate(close_restricted);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct KeyboardEvent
+ {
+ IntPtr @event;
+
+ public IntPtr BaseEvent { get { return GetBaseEvent(@event); } }
+ public IntPtr Event { get { return @event; } }
+ public uint Time { get { return GetTime(@event); } }
+ public uint Key { get { return GetKey(@event); } }
+ public uint KeyCount { get { return GetSeatKeyCount(@event); } }
+ public KeyState KeyState { get { return GetKeyState(@event); } }
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_time", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetTime(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_base_event", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr GetBaseEvent(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_seat_key_count", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetSeatKeyCount(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_key", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetKey(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_key_state", CallingConvention = CallingConvention.Cdecl)]
+ static extern KeyState GetKeyState(IntPtr @event);
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct PointerEvent
+ {
+ IntPtr @event;
+
+ public IntPtr BaseEvent { get { return GetBaseEvent(@event); } }
+ public IntPtr Event { get { return @event; } }
+ public uint Time { get { return GetTime(@event); } }
+ public EvdevButton Button { get { return (EvdevButton)GetButton(@event); } }
+ public uint ButtonCount { get { return GetButtonCount(@event); } }
+ public ButtonState ButtonState { get { return GetButtonState(@event); } }
+ public bool HasAxis(PointerAxis axis) { return HasAxis(@event, axis) != 0; }
+ public double AxisValue(PointerAxis axis) { return GetAxisValue(@event, axis); }
+ public double DeltaX { get { return GetDX(@event); } }
+ public double DeltaY { get { return GetDY(@event); } }
+ public double X { get { return GetAbsX(@event); } }
+ public double Y { get { return GetAbsY(@event); } }
+ public double TransformedX(int width) { return GetAbsXTransformed(@event, width); }
+ public double TransformedY(int height) { return GetAbsYTransformed(@event, height); }
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_time", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetTime(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_base_event", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr GetBaseEvent(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_seat_key_count", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetSeatKeyCount(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_button", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetButton(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_seat_button_count", CallingConvention = CallingConvention.Cdecl)]
+ static extern uint GetButtonCount(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_button_state", CallingConvention = CallingConvention.Cdecl)]
+ static extern ButtonState GetButtonState(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_has_axis", CallingConvention = CallingConvention.Cdecl)]
+ static extern int HasAxis(IntPtr @event, PointerAxis axis);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_axis_value", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetAxisValue(IntPtr @event, PointerAxis axis);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_dx", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetDX(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_dy", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetDY(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_x", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetAbsX(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetAbsY(IntPtr @event);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_x_transformed", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetAbsXTransformed(IntPtr @event, int width);
+
+ [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y_transformed", CallingConvention = CallingConvention.Cdecl)]
+ static extern double GetAbsYTransformed(IntPtr @event, int height);
+
+ public override string ToString ()
+ {
+ return string.Format ("[PointerEvent: BaseEvent={0}, Event={1}, Time={2}, Button={3}, ButtonCount={4}, ButtonState={5}, DeltaX={6}, DeltaY={7}, X={8}, Y={9}]", BaseEvent, Event, Time, Button, ButtonCount, ButtonState, DeltaX, DeltaY, X, Y);
+ }
+ }
+}
+
--- /dev/null
+#region License
+//
+// Poll.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// 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;
+
+namespace Linux
+{
+ partial class Libc
+ {
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ public static extern int poll(ref PollFD fd, IntPtr fd_count, int timeout);
+
+ public static int poll(ref PollFD fd, int fd_count, int timeout)
+ {
+ return poll(ref fd, (IntPtr)fd_count, timeout);
+ }
+ }
+
+ [Flags]
+ enum PollFlags : short
+ {
+ In = 0x01,
+ Pri = 0x02,
+ Out = 0x04,
+ Error = 0x08,
+ Hup = 0x10,
+ Invalid = 0x20,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct PollFD
+ {
+ public int fd;
+ public PollFlags events;
+ public PollFlags revents;
+ }
+}
+
--- /dev/null
+#region License
+//
+// Udev.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// 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;
+
+namespace Linux
+{
+ class Udev
+ {
+ const string lib = "libudev";
+
+ [DllImport(lib, EntryPoint = "udev_new", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr New();
+
+ [DllImport(lib, EntryPoint = "udev_destroy", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void Destroy(IntPtr Udev);
+ }
+}
+
--- /dev/null
+#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.Runtime.InteropServices;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace Linux
+{
+ #region BlittableValueType<T>
+
+ /// <summary>
+ /// Checks whether the specified type parameter is a blittable value type.
+ /// </summary>
+ /// <remarks>
+ /// A blittable value type is a struct that only references other value types recursively,
+ /// which allows it to be passed to unmanaged code directly.
+ /// </remarks>
+ public static class BlittableValueType<T>
+ {
+ #region Fields
+
+ static readonly Type Type;
+ static readonly int stride;
+
+ #endregion
+
+ #region Constructors
+
+ static BlittableValueType()
+ {
+ Type = typeof(T);
+ if (Type.IsValueType && !Type.IsGenericType)
+ {
+ // Does this support generic types? On Mono 2.4.3 it does
+ // On .Net it doesn't.
+ // http://msdn.microsoft.com/en-us/library/5s4920fa.aspx
+ stride = Marshal.SizeOf(typeof(T));
+ }
+ }
+
+ #endregion
+
+ #region Public Members
+
+ /// <summary>
+ /// Gets the size of the type in bytes or 0 for non-blittable types.
+ /// </summary>
+ /// <remarks>
+ /// This property returns 0 for non-blittable types.
+ /// </remarks>
+ public static int Stride { get { return stride; } }
+
+ #region Check
+
+ /// <summary>
+ /// Checks whether the current typename T is blittable.
+ /// </summary>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ public static bool Check()
+ {
+ return Check(Type);
+ }
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">A System.Type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ public static bool Check(Type type)
+ {
+ if (!CheckStructLayoutAttribute(type))
+ Debug.Print("Warning: type {0} does not specify a StructLayoutAttribute with Pack=1. The memory layout of the struct may change between platforms.", type.Name);
+
+ return CheckType(type);
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Private Members
+
+ // Checks whether the parameter is a primitive type or consists of primitive types recursively.
+ // Throws a NotSupportedException if it is not.
+ static bool CheckType(Type type)
+ {
+ //Debug.Print("Checking type {0} (size: {1} bytes).", type.Name, Marshal.SizeOf(type));
+ if (type.IsPrimitive)
+ return true;
+
+ if (!type.IsValueType)
+ return false;
+
+ FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ Debug.Indent();
+ foreach (FieldInfo field in fields)
+ {
+ if (!CheckType(field.FieldType))
+ return false;
+ }
+ Debug.Unindent();
+
+ return Stride != 0;
+ }
+
+ // Checks whether the specified struct defines [StructLayout(LayoutKind.Sequential, Pack=1)]
+ // or [StructLayout(LayoutKind.Explicit)]
+ static bool CheckStructLayoutAttribute(Type type)
+ {
+ StructLayoutAttribute[] attr = (StructLayoutAttribute[])
+ type.GetCustomAttributes(typeof(StructLayoutAttribute), true);
+
+ if ((attr == null) ||
+ (attr != null && attr.Length > 0 && attr[0].Value != LayoutKind.Explicit && attr[0].Pack != 1))
+ return false;
+
+ return true;
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region BlittableValueType
+
+ /// <summary>
+ /// Checks whether the specified type parameter is a blittable value type.
+ /// </summary>
+ /// <remarks>
+ /// A blittable value type is a struct that only references other value types recursively,
+ /// which allows it to be passed to unmanaged code directly.
+ /// </remarks>
+ public static class BlittableValueType
+ {
+ #region Check
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">An instance of the type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ public static bool Check<T>(T type)
+ {
+ return BlittableValueType<T>.Check();
+ }
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">An instance of the type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ [CLSCompliant(false)]
+ public static bool Check<T>(T[] type)
+ {
+ return BlittableValueType<T>.Check();
+ }
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">An instance of the type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ [CLSCompliant(false)]
+ public static bool Check<T>(T[,] type)
+ {
+ return BlittableValueType<T>.Check();
+ }
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">An instance of the type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ [CLSCompliant(false)]
+ public static bool Check<T>(T[, ,] type)
+ {
+ return BlittableValueType<T>.Check();
+ }
+
+ /// <summary>
+ /// Checks whether type is a blittable value type.
+ /// </summary>
+ /// <param name="type">An instance of the type to check.</param>
+ /// <returns>True if T is blittable; false otherwise.</returns>
+ [CLSCompliant(false)]
+ public static bool Check<T>(T[][] type)
+ {
+ return BlittableValueType<T>.Check();
+ }
+
+ #endregion
+
+ #region StrideOf
+
+ /// <summary>
+ /// Returns the size of the specified value type in bytes or 0 if the type is not blittable.
+ /// </summary>
+ /// <typeparam name="T">The value type. Must be blittable.</typeparam>
+ /// <param name="type">An instance of the value type.</param>
+ /// <returns>An integer, specifying the size of the type in bytes.</returns>
+ /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+ public static int StrideOf<T>(T type)
+ {
+ if (!Check(type))
+ throw new ArgumentException("type");
+
+ return BlittableValueType<T>.Stride;
+ }
+
+ /// <summary>
+ /// Returns the size of a single array element in bytes or 0 if the element is not blittable.
+ /// </summary>
+ /// <typeparam name="T">The value type.</typeparam>
+ /// <param name="type">An instance of the value type.</param>
+ /// <returns>An integer, specifying the size of the type in bytes.</returns>
+ /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+ [CLSCompliant(false)]
+ public static int StrideOf<T>(T[] type)
+ {
+ if (!Check(type))
+ throw new ArgumentException("type");
+
+ return BlittableValueType<T>.Stride;
+ }
+
+ /// <summary>
+ /// Returns the size of a single array element in bytes or 0 if the element is not blittable.
+ /// </summary>
+ /// <typeparam name="T">The value type.</typeparam>
+ /// <param name="type">An instance of the value type.</param>
+ /// <returns>An integer, specifying the size of the type in bytes.</returns>
+ /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+ [CLSCompliant(false)]
+ public static int StrideOf<T>(T[,] type)
+ {
+ if (!Check(type))
+ throw new ArgumentException("type");
+
+ return BlittableValueType<T>.Stride;
+ }
+
+ /// <summary>
+ /// Returns the size of a single array element in bytes or 0 if the element is not blittable.
+ /// </summary>
+ /// <typeparam name="T">The value type.</typeparam>
+ /// <param name="type">An instance of the value type.</param>
+ /// <returns>An integer, specifying the size of the type in bytes.</returns>
+ /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+ [CLSCompliant(false)]
+ public static int StrideOf<T>(T[, ,] type)
+ {
+ if (!Check(type))
+ throw new ArgumentException("type");
+
+ return BlittableValueType<T>.Stride;
+ }
+
+ #endregion
+ }
+
+ #endregion
+}
--- /dev/null
+//
+// HelloCube.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2016 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+using System;
+using Crow;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections;
+using System.Xml.Serialization;
+using System.IO;
+//using Cairo;
+namespace CrowIDE
+{
+ class CrowIDE : Application
+ {
+// public Command CMDLoad = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Open"))) { Caption = "Open", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
+// public Command CMDSave = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Save"))) { Caption = "Save", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
+ public Command CMDQuit;
+//// public Command CMDSave = new Command(actionOpenFile) { Caption = "Open...", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
+// public Command CMDQuit = new Command(actionOpenFile) { Caption = "Open...", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
+// public Command CMDCut = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Cut"))) { Caption = "Cut", Icon = new SvgPicture("#Crow.Icons.scissors.svg")};
+// public Command CMDCopy = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Copy"))) { Caption = "Copy", Icon = new SvgPicture("#Crow.Icons.copy-file.svg")};
+// public Command CMDPaste = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Paste"))) { Caption = "Paste", Icon = new SvgPicture("#Crow.Icons.paste-on-document.svg")};
+// public Command CMDHelp = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Help"))) { Caption = "Help", Icon = new SvgPicture("#Crow.Icons.question.svg")};
+ public Command CMDViewGTExp;
+ public Command CMDViewProps;
+ public Command CMDViewProj;
+//
+ ImlVisualEditor imlVE;
+//
+ #region MAIN
+ [STAThread]
+ static void Main ()
+ {
+ try {
+ using (CrowIDE crowApp = new CrowIDE ())
+ crowApp.Run ();
+ } catch (Exception ex) {
+ Console.WriteLine (ex.ToString ());
+ }
+ }
+ #endregion
+
+ #region CTOR
+ public CrowIDE ()
+ : base()
+ {
+ System.Threading.Thread.Sleep (1000);
+ CMDQuit = new Command(new Action(() => Running = false)) { Caption = "Quit", Icon = new SvgPicture("#Crow.Icons.exit-symbol.svg")};
+ CMDViewGTExp = new Command(new Action(() => loadWindow ("#CrowIDE.ui.GTreeExplorer.crow"))) { Caption = "Graphic Tree Explorer"};
+ CMDViewProps = new Command(new Action(() => loadWindow ("#CrowIDE.ui.MemberView.crow"))) { Caption = "Properties View"};
+// CMDViewProj = new Command(new Action(() => loadWindow ("#CrowIDE.ui.CSProjExplorer.crow"))) { Caption = "Project Explorer"};
+//
+// //this.KeyDown += CrowIDE_KeyDown;
+//
+ //this.CrowInterface.LoadInterface ("#CrowIDE.ui.imlEditor.crow").DataSource = this;
+// //GraphicObject go = this.CrowInterface.LoadInterface (@"ui/test.crow");
+ GraphicObject go = this.CrowInterface.LoadInterface (@"#CrowIDE.ui.imlEditor.crow");
+ imlVE = go.FindByName ("crowContainer") as ImlVisualEditor;
+ go.DataSource = this;
+ }
+ #endregion
+
+
+
+// void CrowIDE_KeyDown (object sender, OpenTK.Input.KeyboardKeyEventArgs e)
+// {
+// if (e.Key == OpenTK.Input.Key.Escape) {
+// Quit (null, null);
+// return;
+// } else if (e.Key == OpenTK.Input.Key.F4) {
+// loadWindow ("#CrowIDE.ui.MemberView.crow");
+// } else if (e.Key == OpenTK.Input.Key.F5) {
+// loadWindow ("#CrowIDE.ui.GTreeExplorer.crow");
+// } else if (e.Key == OpenTK.Input.Key.F6) {
+// loadWindow ("#CrowIDE.ui.LQIsExplorer.crow");
+// } else if (e.Key == OpenTK.Input.Key.F7) {
+// loadWindow ("#CrowIDE.ui.CSProjExplorer.crow");
+// }
+// }
+ void loadWindow(string path){
+ try {
+ GraphicObject g = CrowInterface.FindByName (path);
+ if (g != null)
+ return;
+ g = CrowInterface.LoadInterface (path);
+ g.Name = path;
+ g.DataSource = imlVE;
+ } catch (Exception ex) {
+ System.Diagnostics.Debug.WriteLine (ex.ToString ());
+ }
+ }
+ void closeWindow (string path){
+ GraphicObject g = CrowInterface.FindByName (path);
+ if (g != null)
+ CrowInterface.DeleteWidget (g);
+ }
+
+ protected void onCommandSave(object sender, MouseButtonEventArgs e){
+ System.Diagnostics.Debug.WriteLine("save");
+ }
+
+ void actionOpenFile(){
+ System.Diagnostics.Debug.WriteLine ("OpenFile action");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+//
+// DRM.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using DRI.DRM;
+using Linux;
+
+
+namespace DRI {
+ #region DRM callback signatures
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void VBlankCallback(int fd, int sequence, int tv_sec, int tv_usec, IntPtr user_data);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void PageFlipCallback(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data);
+ #endregion
+
+ #region DRM enums
+ public enum EncoderType : uint
+ {
+ NONE=0,
+ DAC=1,
+ TMDS=2,
+ LVDS=3,
+ TVDAC=4,
+ VIRTUAL=5,
+ DSI=6,
+ DPMST=7,
+ DPI=8,
+ }
+ [Flags]public enum PageFlipFlags : uint
+ {
+ FlipEvent = 0x01,
+ FlipAsync = 0x02,
+ FlipFlags = FlipEvent | FlipAsync
+ }
+ /// <summary>Video mode flags, bit compatible with the xorg definitions. </summary>
+ [Flags]public enum VideoMode
+ {
+ PHSYNC = 0x01,
+ NHSYNC = 0x02,
+ PVSYNC = 0x04,
+ NVSYNC = 0x08,
+ INTERLACE = 0x10,
+ DBLSCAN = 0x20,
+ CSYNC = 0x40,
+ PCSYNC = 0x80,
+ NCSYNC = 0x10,
+ HSKEW = 0x0200,
+ BCAST = 0x0400,
+ PIXMUX = 0x0800,
+ DBLCLK = 0x1000,
+ CLKDIV2 = 0x2000,
+ // FLAG_3D_MASK (0x1f<<14)
+ // FLAG_3D_NONE = 0x0;
+ // FLAG_3D_FRAME_PACKING = 0x4000,
+ // FLAG_3D_FIELD_ALTERNATIVE = 0x8000,
+ // FLAG_3D_LINE_ALTERNATIVE (3<<14)
+ // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14)
+ // FLAG_3D_L_DEPTH (5<<14)
+ // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14)
+ // FLAG_3D_TOP_AND_BOTTOM (7<<14)
+ // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
+ }
+ #endregion
+
+ #region DRM structs
+ [StructLayout(LayoutKind.Sequential)]
+ public struct EventContext
+ {
+ public int version;
+ public IntPtr vblank_handler;
+ public IntPtr page_flip_handler;
+ public static readonly int Version = 2;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe public struct drmFrameBuffer {
+ public uint fb_id;
+ public uint width, height;
+ public uint pitch;
+ public uint bpp;
+ public uint depth;
+ /* driver specific handle */
+ public uint handle;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ struct drmClip {
+ public ushort x1;
+ public ushort y1;
+ public ushort x2;
+ public ushort y2;
+ }
+ #endregion
+
+ public class DRIControler : IDisposable {
+ #region PINVOKE
+ const string lib = "libdrm";
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmHandleEvent(int fd, ref EventContext evctx);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeAddFB(int fd, uint width, uint height, byte depth, byte bpp,
+ uint stride, uint bo_handle, out uint buf_id);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeRmFB(int fd, uint bufferId);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeDirtyFB(int fd, uint bufferId, IntPtr clips, uint num_clips);
+ [DllImport(lib,CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern drmFrameBuffer* drmModeGetFB(int fd, uint fb_id);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern void drmModeFreeFB(drmFrameBuffer* ptr);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ static extern int drmModePageFlip(int fd, uint crtc_id, uint fb_id, PageFlipFlags flags, ref int user_data);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ unsafe static extern int drmModeSetCrtc(int fd, uint crtcId, uint bufferId, uint x, uint y, uint* connectors, int count, ref ModeInfo mode);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeSetCursor2(int fd, uint crtcId, uint bo_handle, uint width, uint height, int hot_x, int hot_y);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeMoveCursor(int fd, uint crtcId, uint x, uint y);
+ #endregion
+
+ int fd_gpu = -1;
+ GBM.Device gbmDev;
+ GBM.Surface gbmSurf;
+ public EGL.Context eglctx;
+ EGL.Surface eglSurf;
+
+ Cairo.EGLDevice cairoDev;
+ public Cairo.GLSurface CairoSurf;
+
+ Resources resources = null;
+ Connector connector = null;
+ Crtc currentCrtc = null;
+ ModeInfo currentMode, originalMode;
+ uint originalFB;
+
+ byte bpp = 32;
+ byte depth = 24;
+
+ public volatile int FlipPollingSleep = 1;
+
+ #region CTOR
+ public DRIControler(string gpu_path = "/dev/dri/card0"){
+ fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
+ if (fd_gpu < 0)
+ throw new NotSupportedException("[DRI] Failed to open gpu");
+
+ resources = new Resources (fd_gpu);
+ gbmDev = new GBM.Device (fd_gpu);
+ eglctx = new EGL.Context (gbmDev);
+
+ try {
+ if (defaultConfiguration ())
+ Console.WriteLine ("default config ok");
+ } catch (Exception ex) {
+ Console.WriteLine (ex.ToString());
+ }
+ }
+ #endregion
+
+ public int Width { get { return (int)currentMode.hdisplay; }}
+ public int Height { get { return (int)currentMode.vdisplay; }}
+
+ bool defaultConfiguration (){
+ //select the first connected connector
+ foreach (Connector c in resources.Connectors) {
+ if (c.State == ConnectionStatus.Connected) {
+ connector = c;
+ break;
+ }
+ }
+ if (connector == null)
+ return false;
+
+ currentCrtc = connector.CurrentEncoder.CurrentCrtc;
+ originalMode = currentCrtc.CurrentMode;
+ originalFB = currentCrtc.CurrentFbId;
+ //currentMode = originalMode;
+ currentMode = getNewMode();
+
+ //configure a rendering stack
+ gbmSurf = new GBM.Surface (gbmDev, Width, Height,
+ GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout);
+
+ eglSurf = new EGL.Surface (eglctx, gbmSurf);
+ eglSurf.MakeCurrent ();
+
+ Console.WriteLine ("dpy:{0} ctx{1}", eglctx.dpy, eglctx.ctx);
+
+ cairoDev = new Cairo.EGLDevice (eglctx.dpy, eglctx.ctx);
+ CairoSurf = new Cairo.GLSurface (cairoDev, eglSurf.handle, Width, Height);
+ //cairoSurf = new Cairo.EGLSurface (cairoDev, egl_surface, 1600, 900);
+
+ cairoDev.SetThreadAware (false);
+
+ if (cairoDev.Acquire () != Cairo.Status.Success)
+ Console.WriteLine ("[Cairo]: Failed to acquire egl device.");
+
+// using (Cairo.Context ctx = new Cairo.Context (CairoSurf)) {
+// ctx.Rectangle (0, 0, Width, Height);
+// ctx.SetSourceRGB (0, 0, 1);
+// ctx.Fill ();
+// }
+ //CairoSurf.Flush ();
+ //CairoSurf.SwapBuffers ();
+ //Update ();
+ //setScanOutRegion();
+ //Thread.Sleep (100);
+
+ initPageFlipUpdate ();
+ return true;
+ }
+
+ void handleDestroyFB(ref GBM.gbm_bo bo, ref uint data)
+ {
+ uint fb = data;
+
+ if (fb != 0) {
+ if (drmModeRmFB (fd_gpu, fb) != 0)
+ Console.WriteLine ("DestroyFB failed");
+
+ data = 0;
+ }
+ }
+
+ unsafe GBM.gbm_bo* bo;
+ uint fb;
+
+ unsafe public void Update(){
+ int ret = 0;
+ if (!gbmSurf.HasFreeBuffers)
+ throw new NotSupportedException("[GBM] Out of free buffer");
+ bo = gbmSurf.Lock ();
+
+ if (fb == 0) {
+ ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ }
+ uint connId = connector.Id;
+ ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
+ if (ret != 0)
+ Console.WriteLine ("setCrtc failed: {0}", ret);
+ gbmSurf.Release (bo);
+ }
+
+ static void HandlePageFlip(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data)
+ {
+ user_data = 0;
+ }
+
+ PollFD fds;
+ EventContext evctx;
+ static IntPtr PageFlipPtr = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip);
+ public void initPageFlipUpdate (){
+ fds = new PollFD();
+ fds.fd = fd_gpu;
+ fds.events = PollFlags.In;
+
+ evctx = new EventContext();
+ evctx.version = EventContext.Version;
+ evctx.page_flip_handler = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip);
+ }
+ unsafe public void UpdateWithPageFlip(){
+ GBM.gbm_bo* next_bo;
+ uint fb;
+
+ int timeout = -1;//block ? -1 : 0;
+
+ if (!gbmSurf.HasFreeBuffers)
+ throw new NotSupportedException("[GBM] Out of free buffer");
+
+ next_bo = gbmSurf.Lock ();
+
+ int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, next_bo->Stride, (uint)next_bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ next_bo->SetUserData (ref fb, handleDestroyFB);
+
+ if (bo == null) {
+ uint connId = connector.Id;
+ ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
+ if (ret != 0)
+ Console.WriteLine ("setCrtc failed: {0}", ret);
+ bo = next_bo;
+ } else {
+
+ int is_flip_queued = 1;
+
+ while (drmModePageFlip (fd_gpu, currentCrtc.Id, fb, PageFlipFlags.FlipEvent, ref is_flip_queued) < 0) {
+ //Console.WriteLine ("[DRM] Failed to enqueue framebuffer flip.");
+ Thread.Sleep (1);
+ }
+
+ while (is_flip_queued != 0) {
+ fds.revents = 0;
+ if (Libc.poll (ref fds, 1, timeout) < 0)
+ break;
+ if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
+ break;
+ if ((fds.revents & PollFlags.In) != 0)
+ drmHandleEvent (fd_gpu, ref evctx);
+ else
+ break;
+ Thread.Sleep (FlipPollingSleep);
+ }
+ if (is_flip_queued != 0)
+ Console.WriteLine ("flip canceled");
+
+ gbmSurf.Release (bo);
+ bo = next_bo;
+ }
+ }
+
+ #region cursor
+ GBM.BufferObject boMouseCursor;
+
+ internal void updateCursor (Crow.XCursor cursor) {
+ uint width = 64, height = 64;
+ if (cursor.Width > width || cursor.Height > height){
+ Debug.Print("[DRM] Cursor size {0}x{1} unsupported. Maximum is 64x64.",
+ cursor.Width, cursor.Height);
+ return;
+ }
+ boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888,
+ GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write);
+
+ // Copy cursor.Data into a new buffer of the correct size
+ byte[] cursor_data = new byte[width * height * 4];
+ for (uint y = 0; y < cursor.Height; y++)
+ {
+ uint dst_offset = y * width * 4;
+ uint src_offset = y * cursor.Width * 4;
+ uint src_length = cursor.Width * 4;
+ Array.Copy(
+ cursor.data, src_offset,
+ cursor_data, dst_offset,
+ src_length);
+ }
+
+ boMouseCursor.Data = cursor_data;
+ uint crtcid = currentCrtc.Id;
+
+ unsafe {
+ drmModeSetCursor2 (fd_gpu, crtcid,
+ (uint)boMouseCursor.handle->Handle32, width, height, (int)cursor.Xhot, (int)cursor.Yhot);
+ //drmModeMoveCursor (fd_gpu, crtcid, 0, 0);
+ }
+ }
+ internal void moveCursor (uint x, uint y){
+ drmModeMoveCursor (fd_gpu, currentCrtc.Id, x, y);
+ }
+ #endregion
+
+ ModeInfo getNewMode(){
+ ModeInfo mode = currentCrtc.CurrentMode;
+ mode.clock = 118250;
+ mode.hdisplay = 1600;
+ mode.hsync_start = 1696;
+ mode.hsync_end = 1856;
+ mode.htotal = 2112;
+ mode.vdisplay = 900;
+ mode.vsync_start = 903;
+ mode.vsync_end = 908;
+ mode.vtotal = 934;
+ mode.flags |= (uint)VideoMode.NHSYNC;
+ mode.flags |= (uint)VideoMode.PVSYNC;
+ return mode;
+ }
+
+
+// unsafe public drmPlane GetPlane (uint id) {
+// drmPlane p = new drmPlane();
+// drmPlane* pPlane = ModeGetPlane (fd_gpu, id);
+// if (pPlane != null) {
+// p = *pPlane;
+// ModeFreePlane (pPlane);
+// }
+// return p;
+// }
+// public void SetPlane (drmPlane p, uint flags, uint crtc_w, uint crtc_h, uint src_w, uint src_h) {
+// ModeSetPlane (fd_gpu, p.plane_id, p.crtc_id, p.fb_id, flags,
+// (int)p.crtc_x, (int)p.crtc_y,
+// crtc_w, crtc_h,
+// p.x, p.y,
+// src_w, src_h);
+//
+//
+// }
+
+ #region IDisposable implementation
+ ~DRIControler(){
+ Dispose (false);
+ }
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ bool disposed = false;
+ protected virtual void Dispose (bool disposing){
+ if (disposed)
+ return;
+ unsafe{
+ if (bo != null)
+ gbmSurf.Release (bo);
+ }
+ if (fb != 0)
+ if (drmModeRmFB (fd_gpu, fb) != 0)
+ Console.WriteLine ("DestroyFB failed");
+ if (eglctx != null)
+ eglctx.ResetMakeCurrent ();
+ if (cairoDev != null) {
+ cairoDev.Release ();
+ CairoSurf.Dispose ();
+ cairoDev.Dispose ();
+ cairoDev = null;
+ CairoSurf = null;
+ }
+
+ if (boMouseCursor != null) {
+ drmModeSetCursor2 (fd_gpu, currentCrtc.Id, 0u, 0, 0, 0, 0);
+ boMouseCursor.Dispose ();
+ }
+ boMouseCursor = null;
+ if (connector != null) {
+ uint connId = connector.Id;
+ unsafe {
+ int ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, originalFB, 0, 0, &connId, 1, ref originalMode);
+ if (ret != 0)
+ Console.WriteLine ("restore Crtc failed: {0}", ret);
+ }
+ }
+ if (eglctx != null) {
+ eglctx.ResetMakeCurrent ();
+ if (eglSurf != null)
+ eglSurf.Dispose ();
+ eglSurf = null;
+ if (eglctx != null)
+ eglctx.Dispose ();
+ eglctx = null;
+ }
+
+ if (gbmSurf != null)
+ gbmSurf.Dispose ();
+ if (gbmDev != null)
+ gbmDev.Dispose ();
+ if (currentCrtc != null)
+ currentCrtc.Dispose ();
+ if (connector != null)
+ connector.Dispose ();
+ if (resources != null)
+ resources.Dispose ();
+ resources = null;
+ if (fd_gpu > 0)
+ Libc.close (fd_gpu);
+ fd_gpu = -1;
+ disposed = true;
+ Console.WriteLine ("GPU controler disposed");
+ }
+ #endregion
+ }
+}
\ No newline at end of file
// gr.DrawCote (new Cairo.PointD (hr.Center.X, hr.Y), new Cairo.PointD (hr.Center.X, hr.Bottom));
//hr.Inflate (2);
gr.SetSourceColor (Color.LightGray);
- gr.SetDash (new double[]{ 3.0, 3.0 }, 0.0);
+ //gr.SetDash (new double[]{ 3.0, 2.0 }, 1.0);
gr.Rectangle (hr, 1.0);
}
hr = SelectedItem.ScreenCoordinates(SelectedItem.getSlot ());
hr.Inflate (1);
gr.SetSourceColor (Color.Yellow);
- gr.SetDash (new double[]{ 5.0, 3.0 },0.0);
+ //gr.SetDash (new double[]{ 5.0, 3.0 },0.0);
gr.Rectangle (hr, 1.0);
}
#endregion
--- /dev/null
+//
+// Signals.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.Runtime.InteropServices;
+
+namespace Linux
+{
+ public enum Signal : int {
+ SIGHUP = 1,
+ SIGINT = 2,
+ SIGQUIT = 3,
+ SIGILL = 4,
+ SIGTRAP = 5,
+ SIGABRT = 6,
+ SIGIOT = 6,
+ SIGBUS = 7,
+ SIGFPE = 8,
+ SIGKILL = 9,
+ SIGUSR1 = 10,
+ SIGSEGV = 11,
+ SIGUSR2 = 12,
+ SIGPIPE = 13,
+ SIGALRM = 14,
+ SIGTERM = 15,
+ SIGSTKFLT = 16,
+ SIGCHLD = 17,
+ SIGCONT = 18,
+ SIGSTOP = 19,
+ SIGTSTP = 20,
+ SIGTTIN = 21,
+ SIGTTOU = 22,
+ SIGURG = 23,
+ SIGXCPU = 24,
+ SIGXFSZ = 25,
+ SIGVTALRM = 26,
+ SIGPROF = 27,
+ SIGWINCH = 28,
+ /// <summary>same as SIGPOLL</summary>
+ SIGIO = 29,
+ SIGPWR = 30,
+ SIGSYS = 31,
+ SIGUNUSED = 31
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void SignalHandler(Signal signal);
+
+ public static class Kernel
+ {
+ [DllImport("libc")]
+ public static extern int signal(Signal s, SignalHandler handler);
+ }
+}
+
public BasicTests ()
: base(1600, 900,"test: press <F3> to toogle test files")
{
+
}
int idx = 0;
#endregion
+ #if MEASURE_TIME
+ public List<PerformanceMeasure> PerfMeasures;
+ public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+ public Command CMDViewPerf;
+ #endif
+
void OnClear (object sender, MouseButtonEventArgs e) => TestList = null;
void OnLoadList (object sender, MouseButtonEventArgs e) => TestList = Color.ColorDic.ToList();
//testFiles = new string [] { @"Interfaces/Unsorted/testFileDialog.crow" };
//testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" };
testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
+ //testFiles = new string [] { @"#Tests.Interfaces.perfMsr.crow" };
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Container", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Group", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Unsorted", "*.crow")).ToArray ();
object tc = Color.AirForceBlueRaf;
- Load(testFiles[idx]).DataSource = this;
+ Load (testFiles [idx]).DataSource = this;
+
+ #if MEASURE_TIME
+ PerfMeasures = new List<PerformanceMeasure> (
+ new PerformanceMeasure[] {
+ this.ifaceControl[0].CrowInterface.updateMeasure,
+ this.ifaceControl[0].CrowInterface.layoutingMeasure,
+ this.ifaceControl[0].CrowInterface.clippingMeasure,
+ this.ifaceControl[0].CrowInterface.drawingMeasure,
+ this.ifaceControl[0].glDrawMeasure
+ }
+ );
+ #endif
}
void KeyboardKeyDown1 (object sender, OpenTK.Input.KeyboardKeyEventArgs e)
{
if (IntValue == 1000)
IntValue = 0;
NotifyValueChanged ("PropertyLessBinding", test);
+ #if MEASURE_TIME
+ foreach (PerformanceMeasure m in PerfMeasures)
+ m.NotifyChanges();
+ #endif
}
void onNew(object sender, EventArgs e){
Debug.WriteLine ("menu new clicked");
#endif
if (frameCpt % 3 == 0)
ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps));
- #if MEASURE_TIME
-// foreach (PerformanceMeasure m in PerfMeasures)
-// m.NotifyChanges();
- #endif
}
}
/// Removes delegate from event handler by name
/// </summary>
static void removeEventHandlerByName(object instance, string eventName, string delegateName){
+ if (instance == null){
+ Debug.WriteLine ("RemoveHandlerByName: instance is NULL for Event '" + eventName);
+ return;
+ }
Type t = instance.GetType ();
FieldInfo fiEvt = getEventHandlerField (t, eventName);
if (fiEvt == null) {
#region Events
public event EventHandler<MouseCursorChangedEventArgs> MouseCursorChanged;
public event EventHandler Quit;
+
+ public event EventHandler<MouseWheelEventArgs> MouseWheelChanged;
+ public event EventHandler<MouseButtonEventArgs> MouseButtonUp;
+ public event EventHandler<MouseButtonEventArgs> MouseButtonDown;
+ public event EventHandler<MouseButtonEventArgs> MouseClick;
+ public event EventHandler<MouseMoveEventArgs> MouseMove;
+ public event EventHandler<KeyboardKeyEventArgs> KeyboardKeyDown;
+ public event EventHandler<KeyboardKeyEventArgs> KeyboardKeyUp;
#endregion
#region Public Fields
if (mouseRepeatCount > 0) {
int mc = mouseRepeatCount;
mouseRepeatCount -= mc;
- for (int i = 0; i < mc; i++) {
- FocusedWidget.onMouseClick (this, new MouseButtonEventArgs (Mouse.X, Mouse.Y, MouseButton.Left, true));
+ if (_focusedWidget != null) {
+ for (int i = 0; i < mc; i++) {
+ _focusedWidget.onMouseClick (this, new MouseButtonEventArgs (Mouse.X, Mouse.Y, MouseButton.Left, true));
+ }
}
}
if (keyboardRepeatCount > 0) {
int mc = keyboardRepeatCount;
keyboardRepeatCount -= mc;
- for (int i = 0; i < mc; i++) {
- _focusedWidget.onKeyDown (this, lastKeyDownEvt);
+ if (_focusedWidget != null) {
+ for (int i = 0; i < mc; i++) {
+ _focusedWidget.onKeyDown (this, lastKeyDownEvt);
+ }
}
}
CrowThread[] tmpThreads;
}
public bool ProcessKeyDown(int Key){
Keyboard.SetKeyState((Crow.Key)Key,true);
- if (_focusedWidget == null)
- return false;
+
KeyboardKeyEventArgs e = lastKeyDownEvt = new KeyboardKeyEventArgs((Crow.Key)Key, false, Keyboard);
lastKeyDownEvt.IsRepeat = true;
- _focusedWidget.onKeyDown (this, e);
+
+ KeyboardKeyDown.Raise (this, e);
keyboardRepeatThread = new Thread (keyboardRepeatThreadFunc);
keyboardRepeatThread.IsBackground = true;
keyboardRepeatThread.Start ();
+ if (_focusedWidget == null)
+ return false;
+ _focusedWidget.onKeyDown (this, e);
+
return true;
}
public bool ProcessKeyUp(int Key){
- Keyboard.SetKeyState((Crow.Key)Key,false);
- if (_focusedWidget == null)
- return false;
+ Keyboard.SetKeyState ((Crow.Key)Key, false);
KeyboardKeyEventArgs e = new KeyboardKeyEventArgs((Crow.Key)Key, false, Keyboard);
- _focusedWidget.onKeyUp (this, e);
+ KeyboardKeyUp (this, e);
if (keyboardRepeatThread != null) {
keyboardRepeatOn = false;
keyboardRepeatThread.Abort();
keyboardRepeatThread.Join ();
}
+ if (_focusedWidget == null)
+ return false;
+ _focusedWidget.onKeyUp (this, e);
return true;
}
public bool ProcessKeyPress(char Key){
computeStats ();
}
public void NotifyChanges(){
- if (cptMeasures == 0)
- return;
- NotifyValueChanged("minimum", minimum);
- NotifyValueChanged("maximum", maximum);
- NotifyValueChanged("current", current);
- // NotifyValueChanged("total", total);
- // NotifyValueChanged("cptMeasures", cptMeasures);
- NotifyValueChanged("mean", total / cptMeasures);
+ lock(this){
+ if (cptMeasures == 0)
+ return;
+ NotifyValueChanged("minimum", minimum);
+ NotifyValueChanged("maximum", maximum);
+ NotifyValueChanged("current", current);
+ // NotifyValueChanged("total", total);
+ // NotifyValueChanged("cptMeasures", cptMeasures);
+ NotifyValueChanged("mean", total / cptMeasures);
+ }
}
void computeStats(){
minimum = long.MaxValue;
}
void onResetClick(object sender, MouseButtonEventArgs e){
- ResetStats();
+ lock(this)
+ ResetStats();
}
}
}
using Crow;
using System.Reflection;
using System.Linq;
+using System.Threading;
namespace testDrm
{
[STAThread]
static void Main ()
{
+// int pid = Mono.Unix.Native.Syscall.getpid ();
+// uint gid = Mono.Unix.Native.Syscall.getgid ();
+// int sid = Mono.Unix.Native.Syscall.getsid (0);
+// int newsid = Mono.Unix.Native.Syscall.setsid ();
+//
+// Console.WriteLine ("pid:{0} gid:{1} sid:{2}", pid, gid, sid);
+// Console.WriteLine ("pid:{0} gid:{1} sid:{2}",
+// Mono.Unix.Native.Syscall.getpid (),
+// Mono.Unix.Native.Syscall.getgid (),
+// Mono.Unix.Native.Syscall.getsid (0));
+
System.Threading.Thread.CurrentThread.Name = "Main";
+
try {
- using (TestApp crowApp = new TestApp ()) {
+ using (TestApp crowApp = new TestApp ())
crowApp.Run ();
- }
} catch (Exception ex) {
Console.WriteLine (ex.ToString ());
}
#endregion
- #if MEASURE_TIME
- public List<PerformanceMeasure> PerfMeasures;
- public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
- public Command CMDViewPerf, CMDViewCfg, CMDViewTest0;
- #endif
+ public Command CMDViewPerf, CMDViewCfg, CMDViewTest0, CMDOpen;
public TestApp () : base () {
- #if MEASURE_TIME
- PerfMeasures = new List<PerformanceMeasure> (
- new PerformanceMeasure[] {
- this.CrowInterface.updateMeasure,
- this.CrowInterface.layoutingMeasure,
- this.CrowInterface.clippingMeasure,
- this.CrowInterface.drawingMeasure,
- this.glDrawMeasure
- }
- );
+ CrowInterface.KeyboardKeyDown += CrowInterface_KeyboardKeyDown;
+
CMDViewPerf = new Command(new Action(() => Load ("#testDrm.ui.perfMeasures.crow").DataSource = this)) { Caption = "Performances"};
CMDViewCfg = new Command(new Action(() => Load ("#testDrm.ui.2.crow").DataSource = this)) { Caption = "Configuration"};
CMDViewTest0 = new Command(new Action(() => Load ("#testDrm.ui.0.crow").DataSource = this)) { Caption = "Test view 0"};
- #endif
+ CMDOpen = new Command(new Action(() => {
+ lock (CrowInterface.UpdateMutex) CrowInterface.AddWidget(new FileDialog());})) { Caption = "Open"};
+
+ Load ("#testDrm.ui.menu.crow").DataSource = this;
+
+ initTests ();
+ }
+
+ void CrowInterface_KeyboardKeyDown (object sender, KeyboardKeyEventArgs e)
+ {
+ if (e.Alt){
+ if (e.Key >= Key.F1 && e.Key <= Key.F8){
+ int ttyNum = 0;
+
+ if (int.TryParse (e.Key.ToString ().Substring (1), out ttyNum))
+ Console.WriteLine ("tty switch {0}", ttyNum);
+ this.CurrentState = RunState.DesactivateRequest;
+ }
+ }
}
public int frameTime = 0;
}
}
+ EGL.Surface pbuff;
+ void initTests(){
- public override void Run ()
- {
- Stopwatch frame = new Stopwatch ();
- Load ("#testDrm.ui.menu.crow").DataSource = this;
- int i = 0;
- while(Running){
- try {
- frame.Restart();
- i++;
- base.Run ();
-
- frame.Stop();
- frameTime = (int)frame.ElapsedTicks;
- NotifyValueChanged("frameTime", frameTime);
- if (frameTime > frameMax){
- frameMax = frameTime;
- NotifyValueChanged("frameMax", frameMax);
- }
- if (frameTime < frameMin){
- frameMin = frameTime;
- NotifyValueChanged("frameMin", frameMin);
+
+// pbuff = EGL.Surface.CreatePBuffer(gpu.eglctx,800,600);
+// Console.WriteLine ("pbuff created successfully");
+// Thread.Sleep (100);
+// pbuff.Dispose ();
+ }
+ void testegldraw()
+ {
+ int width = 19;
+ int height = 19;
+ using (Cairo.ImageSurface img = new Cairo.ImageSurface (Cairo.Format.Argb32, gpu.Width, gpu.Height)) {
+ glDrawMeasure.StartCycle ();
+ using (Cairo.Context ctx = new Cairo.Context (img)) {
+ for (int x = 100; x < 800; x += 20) {
+ for (int y = 100; y < 800; y += 20) {
+ ctx.Rectangle (x, y, width, height);
+ ctx.SetSourceRGBA (x / 800.0, y / 800.0, 0.5, 0.5);
+ ctx.Fill ();
+ }
}
- #if MEASURE_TIME
- foreach (PerformanceMeasure m in PerfMeasures)
- m.NotifyChanges();
- #endif
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString());
}
+ glDrawMeasure.StopCycle ();
+ using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) {
+ ctx.SetSourceSurface (img, 0, 0);
+ ctx.Paint ();
+ }
+
}
+
}
+
+ protected override void uiDraw ()
+ {
+ Stopwatch frame = Stopwatch.StartNew ();
+
+ testegldraw ();
+
+ base.uiDraw ();
+
+ frame.Stop();
+ frameTime = (int)frame.ElapsedTicks;
+ NotifyValueChanged("frameTime", frameTime);
+ if (frameTime > frameMax){
+ frameMax = frameTime;
+ NotifyValueChanged("frameMax", frameMax);
+ }
+ if (frameTime < frameMin){
+ frameMin = frameTime;
+ NotifyValueChanged("frameMin", frameMin);
+ }
+ #if MEASURE_TIME
+ foreach (PerformanceMeasure m in PerfMeasures)
+ m.NotifyChanges();
+ #endif
+ }
+
void onQuitClick(object send, Crow.MouseButtonEventArgs e)
{
Running = false;
--- /dev/null
+//
+// defineToEnum.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace testDrm
+{
+ public class defineToEnum
+ {
+ static void Main (){
+ parseDefines("/usr/include/linux/input-event-codes.h");
+ }
+ public struct enumdef {
+ public string name;
+ public int value;
+ }
+ static void parseDefines (string path){
+ Dictionary<string, List<enumdef>> defines = new Dictionary<string, List<enumdef>>();
+
+
+ using (Stream s = new FileStream (path, FileMode.Open,FileAccess.Read)) {
+ using (StreamReader sr = new StreamReader (s)) {
+ while (!sr.EndOfStream) {
+ string l = sr.ReadLine ().Trim();
+ if (!l.StartsWith ("#define"))
+ continue;
+ l = l.Substring (8);
+ string[] ll = l.Split (new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+ string[] cn = ll [0].Split ('_');
+ try {
+ string constName = "";
+ string enumName = cn [0].ToLowerInvariant ().Substring (1);
+ enumName = char.ToUpperInvariant (cn [0][0]) + enumName;
+ for (int i = 1; i < cn.Length; i++) {
+ cn [i] = cn [i].ToLowerInvariant ();
+ constName += char.ToUpperInvariant (cn [i] [0]) + cn [i].Substring (1);
+ }
+ if (char.IsDigit (constName[0]))
+ constName = "_" + constName;
+
+ int value = 0;
+ if (ll [1].StartsWith ("0x")) {
+ if (!int.TryParse (ll [1].Substring (2), System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.CurrentCulture, out value)){
+ Console.WriteLine ("parsing error: " + l);
+ continue;
+ }
+ } else {
+ if (!int.TryParse (ll[1], out value)){
+ Console.WriteLine ("parsing error: " + l);
+ continue;
+ }
+ }
+ if (!defines.ContainsKey(enumName))
+ defines[enumName] = new List<enumdef>();
+ defines[enumName].Add (new enumdef() {name=constName,value=value});
+ } catch (Exception ex) {
+ Console.WriteLine ("failed: " + l);
+ }
+ }
+ }
+ }
+ using (Stream f = new FileStream ("output.txt", FileMode.Create)) {
+ using (StreamWriter sw = new StreamWriter (f)){
+ foreach (string k in defines.Keys) {
+ sw.WriteLine ("public enum {0}Type {{", k);
+ foreach (enumdef ed in defines[k]) {
+ sw.WriteLine ("\t{0,-20}= 0x{1:X4},", ed.name, ed.value);
+ }
+ sw.WriteLine ("}");
+ }
+ }
+ }
+ }
+ }
+}
+
using Linux;
using System.Text;
using OpenTK.Platform.Linux;
+using Linux.oldEvDev;
namespace Crow
{
public class Application : IDisposable
{
+ public enum RunState {
+ ActivateRequest,
+ DesactivateRequest,
+ Paused,
+ Running,
+ }
+ #if MEASURE_TIME
+ public List<PerformanceMeasure> PerfMeasures;
+ protected PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+ #endif
+
public bool Running = true;
- protected DRI.DRIControler gpu;
- Cairo.GLSurface cairoSurf;
+ public volatile RunState CurrentState = RunState.Running;
protected Interface CrowInterface;
+ protected DRI.DRIControler gpu;
+ protected Cairo.GLSurface cairoSurf { get { return gpu?.CairoSurf; }}
protected bool mouseIsInInterface = false;
Thread.Sleep (5);
while (true) {
- CrowInterface.Update ();
- Thread.Sleep (ifaceSleep);
+ if (CurrentState == RunState.Running) {
+ CrowInterface.Update ();
+ Thread.Sleep (ifaceSleep);
+ } else
+ Thread.Sleep (1000);
}
}
-//
- Crow.XCursor cursor;
+
int previousVT = -1, appVT = -1;
public Application(){
if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0)
throw new Exception ("signal handler registation failed");
+// if (Kernel.signal (Signal.SIGUSR2, switch_request_handle) < 0)
+// throw new Exception ("signal handler registation failed");
if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0)
throw new Exception ("SIGINT handler registation failed");
using (VT.VTControler master = new VT.VTControler ()) {
previousVT = master.CurrentVT;
appVT = master.FirstAvailableVT;
+
master.SwitchTo (appVT);
+
try {
master.KDMode = VT.KDMode.GRAPHICS;
+// VT.vt_mode vtm = master.VTMode;
+// vtm.mode = VT.SwitchMode.PROCESS;
+// master.VTMode = vtm;
} catch (Exception ex) {
Console.WriteLine (ex.ToString ());
}
}
- gpu = new DRI.DRIControler();
- cairoSurf = gpu.CairoSurf;
+ initDri ();
+
+ initCrow ();
+
+ initInput ();
+
+ MouseX = gpu.Width / 2;
+ MouseY = gpu.Height / 2;
+
+ initCursor ();
+ }
+
+ #region CROW
+ public GraphicObject Load (string path){
+ return CrowInterface.LoadInterface (path);
+ }
+ void initCrow () {
CrowInterface = new Interface ();
Thread t = new Thread (interfaceThread);
t.IsBackground = true;
t.Start ();
- initInput ();
-
CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height));
+ CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+ #if MEASURE_TIME
+ PerfMeasures = new List<PerformanceMeasure> (
+ new PerformanceMeasure[] {
+ this.CrowInterface.updateMeasure,
+ this.CrowInterface.layoutingMeasure,
+ this.CrowInterface.clippingMeasure,
+ this.CrowInterface.drawingMeasure,
+ this.glDrawMeasure
+ }
+ );
+ #endif
+ }
+ void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+ {
+ gpu.updateCursor (e.NewCursor);
+ }
+ #endregion
+
+ void initDri(){
+ gpu = new DRI.DRIControler();
+ //cairoSurf = gpu.CairoSurf;
+ }
+ void initCursor(){
gpu.updateCursor (XCursor.Default);
- MouseX = gpu.Width / 2;
- MouseY = gpu.Height / 2;
gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4);
- CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
}
+
void switch_request_handle (Signal s){
-// Console.WriteLine ("switch request catched: " + s.ToString());
-// using (VT.VTControler master = new VT.VTControler ()) {
-// Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
-// master.AcknoledgeSwitchRequest ();
-// }
+ Console.WriteLine ("****** switch request catched: " + s.ToString());
+ using (VT.VTControler master = new VT.VTControler ()) {
+ Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
+ master.AcknoledgeSwitchRequest ();
+ }
}
void sigint_handler (Signal s){
Console.WriteLine ("{0}: SIGINT catched");
Running = false;
}
- void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+
+ public virtual void Run ()
{
- gpu.updateCursor (e.NewCursor);
- }
+ int cpt = 0;
+ while(Running){
+ switch (CurrentState) {
+ case RunState.ActivateRequest:
+ activate ();
+ continue;
+ case RunState.DesactivateRequest:
+ desactivate ();
+ continue;
+ case RunState.Paused:
+ Thread.Sleep (1000);
+ continue;
+ }
- public GraphicObject Load (string path){
- return CrowInterface.LoadInterface (path);
+ uiDraw ();
+
+ #if MEASURE_TIME
+ if (cpt%10==0){
+ foreach (PerformanceMeasure m in PerfMeasures)
+ m.NotifyChanges();
+ }
+ #endif
+
+ cpt++;
+ Thread.Sleep (updateSleep);
+ }
}
- public virtual void Run (){
+ protected virtual void uiDraw (){
+// #if MEASURE_TIME
+// glDrawMeasure.StartCycle();
+// #endif
+
bool update = false;
if (updateMousePos) {
Monitor.Exit (CrowInterface.RenderMutex);
}
- if (!update)
- return;
- update = false;
+// if (!update)
+// return;
+// update = false;
+
+
+
cairoSurf.Flush ();
cairoSurf.SwapBuffers ();
- gpu.UpdateWithPageFlip ();
- Thread.Sleep (updateSleep);
+ //gpu.UpdateWithPageFlip ();
+ gpu.Update();
+
+// #if MEASURE_TIME
+// glDrawMeasure.StopCycle ();
+// #endif
}
#region INPUT
long exit;
static readonly object Sync = new object();
- static readonly Crow.Key[] KeyMap = Evdev.KeyMap;
+ static readonly Crow.Key[] KeyMap = EvdevClass.KeyMap;
static long DeviceFDCount;
IntPtr udev;
Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events);
while (Interlocked.Read(ref exit) == 0)
{
+ if (CurrentState != RunState.Running) {
+ Thread.Sleep (1000);
+ continue;
+ }
//drmTimeOut.Restart ();
int ret = Libc.poll(ref poll_fd, 1, -1);
handleKeyboard(LibInput.GetKeyboardEvent(pevent));
break;
//
- // case InputEventType.PointerAxis:
- // HandlePointerAxis(GetMouse(device), LibInput.GetPointerEvent(pevent));
- // break;
- //
+ case InputEventType.PointerAxis:
+ handlePointerAxis(LibInput.GetPointerEvent(pevent));
+ break;
+
case InputEventType.PointerButton:
handlePointerButton (LibInput.GetPointerEvent(pevent));
break;
handlePointerMotion (LibInput.GetPointerEvent(pevent));
break;
- // case InputEventType.PointerMotionAbsolute:
- // HandlePointerMotionAbsolute(GetMouse(device), LibInput.GetPointerEvent(pevent));
- // break;
+// case InputEventType.PointerMotionAbsolute:
+// handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent));
+// break;
}
}
int roundDelta (double d){
return d > 0 ? (int)Math.Ceiling(d) : (int)Math.Floor (d);
}
-
+ void handlePointerAxis(PointerEvent e){
+// if (e.HasAxis(PointerAxis.HorizontalScroll))
+// {
+// CrowInterface.ProcessMouseWheelChanged ((float)e.AxisValue (PointerAxis.HorizontalScroll));
+// }
+ if (e.HasAxis(PointerAxis.VerticalScroll))
+ {
+ CrowInterface.ProcessMouseWheelChanged ((float)-e.AxisValue (PointerAxis.VerticalScroll));
+ }
+ }
void handlePointerMotion(PointerEvent e)
{
MouseX += roundDelta (e.DeltaX);
KeyModifiers curModifiers = KeyModifiers.None;
void handleKeyboard(KeyboardEvent e)
- {
- return;
- int key = (int)Evdev.KeyMap [e.Key];
+ {
+ int key = (int)EvdevClass.KeyMap [e.Key];
Key k = (Key)key;
if (e.KeyState == KeyState.Pressed) {
CrowInterface.ProcessKeyDown (key);
#endregion
+
+
+ void desactivate () {
+ CurrentState = RunState.Paused;
+
+ //cairoSurf = null;
+ gpu.Dispose ();
+ gpu = null;
+ }
+ void activate (){
+ initDri();
+ initCursor ();
+
+ CurrentState = RunState.Running;
+ }
+
#region IDisposable implementation
~Application(){
Dispose (false);
using System.Diagnostics;
using System.Reflection;
-namespace Crow
+namespace Linux
{
#region BlittableValueType<T>
Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers);
return;
}
-// string tmp = keymap [curModifiers] [e.Key];
+ string tmp = keymap [curModifiers] [e.Key];
// if (string.IsNullOrEmpty (tmp))
// return;
// if (char.IsControl (tmp[0]))
--- /dev/null
+//
+// Device.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.Runtime.InteropServices;
+
+namespace Linux.Evdev
+{
+ public enum GrabMode {
+ Grab = 3,
+ Ungrab = 4
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct InputAbsInfo
+ {
+ public int Value;
+ public int Minimum;
+ public int Maximum;
+ public int Fuzz;
+ public int Flat;
+ public int Resolution;
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct InputId
+ {
+ public ushort BusType;
+ public ushort Vendor;
+ public ushort Product;
+ public ushort Version;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe public struct KeyMapEntry
+ {
+ public byte Flags;
+ public byte Length;
+ public ushort Index;
+ public uint Keycode;
+ fixed sbyte scancode[32];
+
+ public string ScanCode {
+ get {
+ fixed(sbyte* bytes = scancode) {
+ string test = new string (bytes);
+ return test;
+ }
+
+ }
+ }
+ public override string ToString ()
+ {
+ return string.Format ("Flags={0} Length={1} Index={2} KeyCode={3} Scancode={4}",
+ Flags, Length, Index, Keycode, ScanCode);
+ }
+
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct InputEvent
+ {
+ public TimeVal Time;
+ ushort type;
+ public ushort Code;
+ public int Value;
+
+ public EvType Type { get { return (EvType)type; } }
+ public string CodeName { get { return Marshal.PtrToStringAuto(Device.libevdev_event_code_get_name ((uint)type,(uint)Code)); } }
+ public override string ToString ()
+ {
+ return string.Format ("[Event: {0}:{1} Type={2} Code={3} Value={4} CodeName={5}]",
+ Time.Seconds, Time.MicroSeconds, Type, Code, Value, CodeName);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TimeVal
+ {
+ public IntPtr Seconds;
+ public IntPtr MicroSeconds;
+ }
+
+ public class Device : IDisposable
+ {
+ public const int SUCCESS = 0;
+ public const int SYNC = 1;
+
+ const string libevdev = "libevdev";
+
+ #region pinvoke
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_new_from_fd (int fd, out IntPtr handle);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void libevdev_free (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr libevdev_get_name (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_get_id_bustype (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_get_id_product (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_get_id_vendor (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_get_id_version (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr libevdev_get_phys (IntPtr dev);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr libevdev_get_uniq (IntPtr dev);
+
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr libevdev_event_type_get_name (uint type);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr libevdev_event_code_get_name (uint type, uint code);
+
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_get_repeat (IntPtr dev, out int delay, out int period);
+
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_has_event_type (IntPtr dev, EvType type);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_has_event_code (IntPtr dev, EvType type, uint code);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_has_property (IntPtr dev, PropertyType prop);
+
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_grab (IntPtr dev, GrabMode mode);
+ [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int libevdev_next_event (IntPtr dev, ReadFlag flags, out InputEvent evt);
+ #endregion
+
+ int fd = -1;
+ IntPtr handle = IntPtr.Zero;
+
+ public Device (string devPath)
+ {
+ fd = Libc.open(devPath, OpenFlags.ReadOnly | OpenFlags.NonBlock);
+ if (fd < 0)
+ throw new Exception (string.Format ("EVDEV: faile to open {0}", devPath));
+ int ret = libevdev_new_from_fd (fd, out handle);
+ if (ret < 0)
+ throw new Exception (string.Format ("EVDEV: ibevdev_new_from_fd failed on {0}: {1}", devPath, ret));
+ }
+ public Device (int num) : this ("/dev/input/event" + num)
+ {
+ }
+
+ public string Name { get { return Marshal.PtrToStringAuto(libevdev_get_name (handle)); }}
+ public string PhysLocation { get { return Marshal.PtrToStringAuto(libevdev_get_phys (handle)); }}
+ public string UniqueId { get { return Marshal.PtrToStringAuto (libevdev_get_uniq (handle)); }}
+ public int BusTypeId { get { return libevdev_get_id_bustype (handle); }}
+ public int ProductId { get { return libevdev_get_id_product (handle); }}
+ public int VendorId { get { return libevdev_get_id_vendor (handle); }}
+ public int VersionId { get { return libevdev_get_id_version (handle); }}
+
+ public bool HasEventOfType (EvType evType) => libevdev_has_event_type (handle, evType) > 0;
+ public bool HasEventCodeOfType (EvType evType, uint evCode) => libevdev_has_event_code (handle, evType, evCode) > 0;
+ public bool HasEventOfType (PropertyType propType) => libevdev_has_property (handle, propType) > 0;
+
+ public bool GetNextEvent (out InputEvent evt){
+ return libevdev_next_event (handle, ReadFlag.Normal, out evt) == 0;
+ }
+
+ public bool TryGrab (){
+ return libevdev_grab (handle, GrabMode.Grab) == 0;
+ }
+ public bool TryRelease (){
+ return libevdev_grab (handle, GrabMode.Ungrab) == 0;
+ }
+ const uint EVIOCGKEYCODE = 0x80084504;
+ const uint EVIOCGKEYCODE_V2 = 0x80284504;
+
+ public void test(){
+ int[] codes = new int[2];
+
+ for (int i=0; i<130; i++) {
+
+ codes[0] = i;
+ int ret = Libc.ioctl (fd, EVIOCGKEYCODE, codes);
+ if(ret!=0) {
+ Console.WriteLine ("evdev ioctl error: " + ret);
+ }else
+ Console.WriteLine ("[0]= {0}, [1] = {1}\n", codes[0], codes[1]);
+ }
+ }
+ public void test2(){
+ KeyMapEntry kme = default(KeyMapEntry);
+
+ for (int i=0; i<130; i++) {
+ kme.Flags = 1;
+ kme.Index = (ushort)i;
+ kme.Length = sizeof(uint);
+ int ret = Libc.ioctl (fd, EVIOCGKEYCODE_V2, ref kme);
+ if(ret!=0) {
+ Console.WriteLine ("evdev ioctl error: " + ret);
+ }else
+ Console.WriteLine (kme.ToString());
+ }
+ }
+// public KeyMapEntry GetKeyMapEntry (KeyType k){
+// KeyMapEntry kme;
+// return kme;
+// }
+ #region IDisposable implementation
+ ~Device(){
+ Dispose (false);
+ }
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ protected virtual void Dispose (bool disposing){
+ if (handle != IntPtr.Zero)
+ libevdev_free (handle);
+ handle = IntPtr.Zero;
+ if (fd > 0)
+ Libc.close(fd);
+ fd = -1;
+ }
+ #endregion
+ }
+}
+
--- /dev/null
+//
+// Enums.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+
+namespace Linux.Evdev
+{
+ [Flags]public enum ReadFlag {
+ Sync = 0x01, /**< Process data in sync mode */
+ Normal = 0x02, /**< Process data in normal mode */
+ ForceSync = 0x04, /**< Pretend the next event is a SYN_DROPPED and require the caller to sync */
+ Blocking = 0x08 /**< The fd is not in O_NONBLOCK and a read may block */
+ }
+
+ public enum PropertyType : uint {
+ Pointer = 0x0000,
+ Direct = 0x0001,
+ Buttonpad = 0x0002,
+ SemiMt = 0x0003,
+ Topbuttonpad = 0x0004,
+ PointingStick = 0x0005,
+ Accelerometer = 0x0006,
+ Max = 0x001F,
+ }
+ public enum EvType : uint {
+ Syn = 0x0000,
+ Key = 0x0001,
+ Rel = 0x0002,
+ Abs = 0x0003,
+ Msc = 0x0004,
+ Sw = 0x0005,
+ Led = 0x0011,
+ Snd = 0x0012,
+ Rep = 0x0014,
+ Ff = 0x0015,
+ Pwr = 0x0016,
+ FfStatus = 0x0017,
+ Max = 0x001F,
+ Cnt = (Max+1),
+ }
+ public enum SynType : uint {
+ Report = 0x0000,
+ Config = 0x0001,
+ MtReport = 0x0002,
+ Dropped = 0x0003,
+ Max = 0x000F,
+ }
+ public enum KeyType : uint {
+ Reserved = 0x0000,
+ Esc = 0x0001,
+ _1 = 0x0002,
+ _2 = 0x0003,
+ _3 = 0x0004,
+ _4 = 0x0005,
+ _5 = 0x0006,
+ _6 = 0x0007,
+ _7 = 0x0008,
+ _8 = 0x0009,
+ _9 = 0x000A,
+ _0 = 0x000B,
+ Minus = 0x000C,
+ Equal = 0x000D,
+ Backspace = 0x000E,
+ Tab = 0x000F,
+ Q = 0x0010,
+ W = 0x0011,
+ E = 0x0012,
+ R = 0x0013,
+ T = 0x0014,
+ Y = 0x0015,
+ U = 0x0016,
+ I = 0x0017,
+ O = 0x0018,
+ P = 0x0019,
+ Leftbrace = 0x001A,
+ Rightbrace = 0x001B,
+ Enter = 0x001C,
+ Leftctrl = 0x001D,
+ A = 0x001E,
+ S = 0x001F,
+ D = 0x0020,
+ F = 0x0021,
+ G = 0x0022,
+ H = 0x0023,
+ J = 0x0024,
+ K = 0x0025,
+ L = 0x0026,
+ Semicolon = 0x0027,
+ Apostrophe = 0x0028,
+ Grave = 0x0029,
+ Leftshift = 0x002A,
+ Backslash = 0x002B,
+ Z = 0x002C,
+ X = 0x002D,
+ C = 0x002E,
+ V = 0x002F,
+ B = 0x0030,
+ N = 0x0031,
+ M = 0x0032,
+ Comma = 0x0033,
+ Dot = 0x0034,
+ Slash = 0x0035,
+ Rightshift = 0x0036,
+ Kpasterisk = 0x0037,
+ Leftalt = 0x0038,
+ Space = 0x0039,
+ Capslock = 0x003A,
+ F1 = 0x003B,
+ F2 = 0x003C,
+ F3 = 0x003D,
+ F4 = 0x003E,
+ F5 = 0x003F,
+ F6 = 0x0040,
+ F7 = 0x0041,
+ F8 = 0x0042,
+ F9 = 0x0043,
+ F10 = 0x0044,
+ Numlock = 0x0045,
+ Scrolllock = 0x0046,
+ Kp7 = 0x0047,
+ Kp8 = 0x0048,
+ Kp9 = 0x0049,
+ Kpminus = 0x004A,
+ Kp4 = 0x004B,
+ Kp5 = 0x004C,
+ Kp6 = 0x004D,
+ Kpplus = 0x004E,
+ Kp1 = 0x004F,
+ Kp2 = 0x0050,
+ Kp3 = 0x0051,
+ Kp0 = 0x0052,
+ Kpdot = 0x0053,
+ Zenkakuhankaku = 0x0055,
+ _102nd = 0x0056,
+ F11 = 0x0057,
+ F12 = 0x0058,
+ Ro = 0x0059,
+ Katakana = 0x005A,
+ Hiragana = 0x005B,
+ Henkan = 0x005C,
+ Katakanahiragana = 0x005D,
+ Muhenkan = 0x005E,
+ Kpjpcomma = 0x005F,
+ Kpenter = 0x0060,
+ Rightctrl = 0x0061,
+ Kpslash = 0x0062,
+ Sysrq = 0x0063,
+ Rightalt = 0x0064,
+ Linefeed = 0x0065,
+ Home = 0x0066,
+ Up = 0x0067,
+ Pageup = 0x0068,
+ Left = 0x0069,
+ Right = 0x006A,
+ End = 0x006B,
+ Down = 0x006C,
+ Pagedown = 0x006D,
+ Insert = 0x006E,
+ Delete = 0x006F,
+ Macro = 0x0070,
+ Mute = 0x0071,
+ Volumedown = 0x0072,
+ Volumeup = 0x0073,
+ Power = 0x0074,
+ Kpequal = 0x0075,
+ Kpplusminus = 0x0076,
+ Pause = 0x0077,
+ Scale = 0x0078,
+ Kpcomma = 0x0079,
+ Hangeul = 0x007A,
+ Hanja = 0x007B,
+ Yen = 0x007C,
+ Leftmeta = 0x007D,
+ Rightmeta = 0x007E,
+ Compose = 0x007F,
+ Stop = 0x0080,
+ Again = 0x0081,
+ Props = 0x0082,
+ Undo = 0x0083,
+ Front = 0x0084,
+ Copy = 0x0085,
+ Open = 0x0086,
+ Paste = 0x0087,
+ Find = 0x0088,
+ Cut = 0x0089,
+ Help = 0x008A,
+ Menu = 0x008B,
+ Calc = 0x008C,
+ Setup = 0x008D,
+ Sleep = 0x008E,
+ Wakeup = 0x008F,
+ File = 0x0090,
+ Sendfile = 0x0091,
+ Deletefile = 0x0092,
+ Xfer = 0x0093,
+ Prog1 = 0x0094,
+ Prog2 = 0x0095,
+ Www = 0x0096,
+ Msdos = 0x0097,
+ Coffee = 0x0098,
+ RotateDisplay = 0x0099,
+ Cyclewindows = 0x009A,
+ Mail = 0x009B,
+ Bookmarks = 0x009C,
+ Computer = 0x009D,
+ Back = 0x009E,
+ Forward = 0x009F,
+ Closecd = 0x00A0,
+ Ejectcd = 0x00A1,
+ Ejectclosecd = 0x00A2,
+ Nextsong = 0x00A3,
+ Playpause = 0x00A4,
+ Previoussong = 0x00A5,
+ Stopcd = 0x00A6,
+ Record = 0x00A7,
+ Rewind = 0x00A8,
+ Phone = 0x00A9,
+ Iso = 0x00AA,
+ Config = 0x00AB,
+ Homepage = 0x00AC,
+ Refresh = 0x00AD,
+ Exit = 0x00AE,
+ Move = 0x00AF,
+ Edit = 0x00B0,
+ Scrollup = 0x00B1,
+ Scrolldown = 0x00B2,
+ Kpleftparen = 0x00B3,
+ Kprightparen = 0x00B4,
+ New = 0x00B5,
+ Redo = 0x00B6,
+ F13 = 0x00B7,
+ F14 = 0x00B8,
+ F15 = 0x00B9,
+ F16 = 0x00BA,
+ F17 = 0x00BB,
+ F18 = 0x00BC,
+ F19 = 0x00BD,
+ F20 = 0x00BE,
+ F21 = 0x00BF,
+ F22 = 0x00C0,
+ F23 = 0x00C1,
+ F24 = 0x00C2,
+ Playcd = 0x00C8,
+ Pausecd = 0x00C9,
+ Prog3 = 0x00CA,
+ Prog4 = 0x00CB,
+ Dashboard = 0x00CC,
+ Suspend = 0x00CD,
+ Close = 0x00CE,
+ Play = 0x00CF,
+ Fastforward = 0x00D0,
+ Bassboost = 0x00D1,
+ Print = 0x00D2,
+ Hp = 0x00D3,
+ Camera = 0x00D4,
+ Sound = 0x00D5,
+ Question = 0x00D6,
+ Email = 0x00D7,
+ Chat = 0x00D8,
+ Search = 0x00D9,
+ Connect = 0x00DA,
+ Finance = 0x00DB,
+ Sport = 0x00DC,
+ Shop = 0x00DD,
+ Alterase = 0x00DE,
+ Cancel = 0x00DF,
+ Brightnessdown = 0x00E0,
+ Brightnessup = 0x00E1,
+ Media = 0x00E2,
+ Switchvideomode = 0x00E3,
+ Kbdillumtoggle = 0x00E4,
+ Kbdillumdown = 0x00E5,
+ Kbdillumup = 0x00E6,
+ Send = 0x00E7,
+ Reply = 0x00E8,
+ Forwardmail = 0x00E9,
+ Save = 0x00EA,
+ Documents = 0x00EB,
+ Battery = 0x00EC,
+ Bluetooth = 0x00ED,
+ Wlan = 0x00EE,
+ Uwb = 0x00EF,
+ Unknown = 0x00F0,
+ VideoNext = 0x00F1,
+ VideoPrev = 0x00F2,
+ BrightnessCycle = 0x00F3,
+ BrightnessAuto = 0x00F4,
+ DisplayOff = 0x00F5,
+ Wwan = 0x00F6,
+ Rfkill = 0x00F7,
+ Micmute = 0x00F8,
+ Ok = 0x0160,
+ Select = 0x0161,
+ Goto = 0x0162,
+ Clear = 0x0163,
+ Power2 = 0x0164,
+ Option = 0x0165,
+ Info = 0x0166,
+ Time = 0x0167,
+ Vendor = 0x0168,
+ Archive = 0x0169,
+ Program = 0x016A,
+ Channel = 0x016B,
+ Favorites = 0x016C,
+ Epg = 0x016D,
+ Pvr = 0x016E,
+ Mhp = 0x016F,
+ Language = 0x0170,
+ Title = 0x0171,
+ Subtitle = 0x0172,
+ Angle = 0x0173,
+ Zoom = 0x0174,
+ Mode = 0x0175,
+ Keyboard = 0x0176,
+ Screen = 0x0177,
+ Pc = 0x0178,
+ Tv = 0x0179,
+ Tv2 = 0x017A,
+ Vcr = 0x017B,
+ Vcr2 = 0x017C,
+ Sat = 0x017D,
+ Sat2 = 0x017E,
+ Cd = 0x017F,
+ Tape = 0x0180,
+ Radio = 0x0181,
+ Tuner = 0x0182,
+ Player = 0x0183,
+ Text = 0x0184,
+ Dvd = 0x0185,
+ Aux = 0x0186,
+ Mp3 = 0x0187,
+ Audio = 0x0188,
+ Video = 0x0189,
+ Directory = 0x018A,
+ List = 0x018B,
+ Memo = 0x018C,
+ Calendar = 0x018D,
+ Red = 0x018E,
+ Green = 0x018F,
+ Yellow = 0x0190,
+ Blue = 0x0191,
+ Channelup = 0x0192,
+ Channeldown = 0x0193,
+ First = 0x0194,
+ Last = 0x0195,
+ Ab = 0x0196,
+ Next = 0x0197,
+ Restart = 0x0198,
+ Slow = 0x0199,
+ Shuffle = 0x019A,
+ Break = 0x019B,
+ Previous = 0x019C,
+ Digits = 0x019D,
+ Teen = 0x019E,
+ Twen = 0x019F,
+ Videophone = 0x01A0,
+ Games = 0x01A1,
+ Zoomin = 0x01A2,
+ Zoomout = 0x01A3,
+ Zoomreset = 0x01A4,
+ Wordprocessor = 0x01A5,
+ Editor = 0x01A6,
+ Spreadsheet = 0x01A7,
+ Graphicseditor = 0x01A8,
+ Presentation = 0x01A9,
+ Database = 0x01AA,
+ News = 0x01AB,
+ Voicemail = 0x01AC,
+ Addressbook = 0x01AD,
+ Messenger = 0x01AE,
+ Displaytoggle = 0x01AF,
+ Spellcheck = 0x01B0,
+ Logoff = 0x01B1,
+ Dollar = 0x01B2,
+ Euro = 0x01B3,
+ Frameback = 0x01B4,
+ Frameforward = 0x01B5,
+ ContextMenu = 0x01B6,
+ MediaRepeat = 0x01B7,
+ _10channelsup = 0x01B8,
+ _10channelsdown = 0x01B9,
+ Images = 0x01BA,
+ DelEol = 0x01C0,
+ DelEos = 0x01C1,
+ InsLine = 0x01C2,
+ DelLine = 0x01C3,
+ Fn = 0x01D0,
+ FnEsc = 0x01D1,
+ FnF1 = 0x01D2,
+ FnF2 = 0x01D3,
+ FnF3 = 0x01D4,
+ FnF4 = 0x01D5,
+ FnF5 = 0x01D6,
+ FnF6 = 0x01D7,
+ FnF7 = 0x01D8,
+ FnF8 = 0x01D9,
+ FnF9 = 0x01DA,
+ FnF10 = 0x01DB,
+ FnF11 = 0x01DC,
+ FnF12 = 0x01DD,
+ Fn1 = 0x01DE,
+ Fn2 = 0x01DF,
+ FnD = 0x01E0,
+ FnE = 0x01E1,
+ FnF = 0x01E2,
+ FnS = 0x01E3,
+ FnB = 0x01E4,
+ BrlDot1 = 0x01F1,
+ BrlDot2 = 0x01F2,
+ BrlDot3 = 0x01F3,
+ BrlDot4 = 0x01F4,
+ BrlDot5 = 0x01F5,
+ BrlDot6 = 0x01F6,
+ BrlDot7 = 0x01F7,
+ BrlDot8 = 0x01F8,
+ BrlDot9 = 0x01F9,
+ BrlDot10 = 0x01FA,
+ Numeric0 = 0x0200,
+ Numeric1 = 0x0201,
+ Numeric2 = 0x0202,
+ Numeric3 = 0x0203,
+ Numeric4 = 0x0204,
+ Numeric5 = 0x0205,
+ Numeric6 = 0x0206,
+ Numeric7 = 0x0207,
+ Numeric8 = 0x0208,
+ Numeric9 = 0x0209,
+ NumericStar = 0x020A,
+ NumericPound = 0x020B,
+ NumericA = 0x020C,
+ NumericB = 0x020D,
+ NumericC = 0x020E,
+ NumericD = 0x020F,
+ CameraFocus = 0x0210,
+ WpsButton = 0x0211,
+ TouchpadToggle = 0x0212,
+ TouchpadOn = 0x0213,
+ TouchpadOff = 0x0214,
+ CameraZoomin = 0x0215,
+ CameraZoomout = 0x0216,
+ CameraUp = 0x0217,
+ CameraDown = 0x0218,
+ CameraLeft = 0x0219,
+ CameraRight = 0x021A,
+ AttendantOn = 0x021B,
+ AttendantOff = 0x021C,
+ AttendantToggle = 0x021D,
+ LightsToggle = 0x021E,
+ AlsToggle = 0x0230,
+ Buttonconfig = 0x0240,
+ Taskmanager = 0x0241,
+ Journal = 0x0242,
+ Controlpanel = 0x0243,
+ Appselect = 0x0244,
+ Screensaver = 0x0245,
+ Voicecommand = 0x0246,
+ BrightnessMin = 0x0250,
+ BrightnessMax = 0x0251,
+ KbdinputassistPrev = 0x0260,
+ KbdinputassistNext = 0x0261,
+ KbdinputassistPrevgroup= 0x0262,
+ KbdinputassistNextgroup= 0x0263,
+ KbdinputassistAccept= 0x0264,
+ KbdinputassistCancel= 0x0265,
+ RightUp = 0x0266,
+ RightDown = 0x0267,
+ LeftUp = 0x0268,
+ LeftDown = 0x0269,
+ RootMenu = 0x026A,
+ MediaTopMenu = 0x026B,
+ Numeric11 = 0x026C,
+ Numeric12 = 0x026D,
+ AudioDesc = 0x026E,
+ _3dMode = 0x026F,
+ NextFavorite = 0x0270,
+ StopRecord = 0x0271,
+ PauseRecord = 0x0272,
+ Vod = 0x0273,
+ Unmute = 0x0274,
+ Fastreverse = 0x0275,
+ Slowreverse = 0x0276,
+ Data = 0x0277,
+ Max = 0x02FF,
+ }
+ public enum BtnType : uint {
+ Misc = 0x0100,
+ _0 = 0x0100,
+ _1 = 0x0101,
+ _2 = 0x0102,
+ _3 = 0x0103,
+ _4 = 0x0104,
+ _5 = 0x0105,
+ _6 = 0x0106,
+ _7 = 0x0107,
+ _8 = 0x0108,
+ _9 = 0x0109,
+ Mouse = 0x0110,
+ Left = 0x0110,
+ Right = 0x0111,
+ Middle = 0x0112,
+ Side = 0x0113,
+ Extra = 0x0114,
+ Forward = 0x0115,
+ Back = 0x0116,
+ Task = 0x0117,
+ Joystick = 0x0120,
+ Trigger = 0x0120,
+ Thumb = 0x0121,
+ Thumb2 = 0x0122,
+ Top = 0x0123,
+ Top2 = 0x0124,
+ Pinkie = 0x0125,
+ Base = 0x0126,
+ Base2 = 0x0127,
+ Base3 = 0x0128,
+ Base4 = 0x0129,
+ Base5 = 0x012A,
+ Base6 = 0x012B,
+ Dead = 0x012F,
+ Gamepad = 0x0130,
+ South = 0x0130,
+ East = 0x0131,
+ C = 0x0132,
+ North = 0x0133,
+ West = 0x0134,
+ Z = 0x0135,
+ Tl = 0x0136,
+ Tr = 0x0137,
+ Tl2 = 0x0138,
+ Tr2 = 0x0139,
+ Select = 0x013A,
+ Start = 0x013B,
+ Mode = 0x013C,
+ Thumbl = 0x013D,
+ Thumbr = 0x013E,
+ Digi = 0x0140,
+ ToolPen = 0x0140,
+ ToolRubber = 0x0141,
+ ToolBrush = 0x0142,
+ ToolPencil = 0x0143,
+ ToolAirbrush = 0x0144,
+ ToolFinger = 0x0145,
+ ToolMouse = 0x0146,
+ ToolLens = 0x0147,
+ ToolQuinttap = 0x0148,
+ Touch = 0x014A,
+ Stylus = 0x014B,
+ Stylus2 = 0x014C,
+ ToolDoubletap = 0x014D,
+ ToolTripletap = 0x014E,
+ ToolQuadtap = 0x014F,
+ Wheel = 0x0150,
+ GearDown = 0x0150,
+ GearUp = 0x0151,
+ DpadUp = 0x0220,
+ DpadDown = 0x0221,
+ DpadLeft = 0x0222,
+ DpadRight = 0x0223,
+ TriggerHappy = 0x02C0,
+ TriggerHappy1 = 0x02C0,
+ TriggerHappy2 = 0x02C1,
+ TriggerHappy3 = 0x02C2,
+ TriggerHappy4 = 0x02C3,
+ TriggerHappy5 = 0x02C4,
+ TriggerHappy6 = 0x02C5,
+ TriggerHappy7 = 0x02C6,
+ TriggerHappy8 = 0x02C7,
+ TriggerHappy9 = 0x02C8,
+ TriggerHappy10 = 0x02C9,
+ TriggerHappy11 = 0x02CA,
+ TriggerHappy12 = 0x02CB,
+ TriggerHappy13 = 0x02CC,
+ TriggerHappy14 = 0x02CD,
+ TriggerHappy15 = 0x02CE,
+ TriggerHappy16 = 0x02CF,
+ TriggerHappy17 = 0x02D0,
+ TriggerHappy18 = 0x02D1,
+ TriggerHappy19 = 0x02D2,
+ TriggerHappy20 = 0x02D3,
+ TriggerHappy21 = 0x02D4,
+ TriggerHappy22 = 0x02D5,
+ TriggerHappy23 = 0x02D6,
+ TriggerHappy24 = 0x02D7,
+ TriggerHappy25 = 0x02D8,
+ TriggerHappy26 = 0x02D9,
+ TriggerHappy27 = 0x02DA,
+ TriggerHappy28 = 0x02DB,
+ TriggerHappy29 = 0x02DC,
+ TriggerHappy30 = 0x02DD,
+ TriggerHappy31 = 0x02DE,
+ TriggerHappy32 = 0x02DF,
+ TriggerHappy33 = 0x02E0,
+ TriggerHappy34 = 0x02E1,
+ TriggerHappy35 = 0x02E2,
+ TriggerHappy36 = 0x02E3,
+ TriggerHappy37 = 0x02E4,
+ TriggerHappy38 = 0x02E5,
+ TriggerHappy39 = 0x02E6,
+ TriggerHappy40 = 0x02E7,
+ }
+ public enum RelType : uint {
+ X = 0x0000,
+ Y = 0x0001,
+ Z = 0x0002,
+ Rx = 0x0003,
+ Ry = 0x0004,
+ Rz = 0x0005,
+ Hwheel = 0x0006,
+ Dial = 0x0007,
+ Wheel = 0x0008,
+ Misc = 0x0009,
+ Max = 0x000F,
+ }
+ public enum AbsType : uint {
+ X = 0x0000,
+ Y = 0x0001,
+ Z = 0x0002,
+ Rx = 0x0003,
+ Ry = 0x0004,
+ Rz = 0x0005,
+ Throttle = 0x0006,
+ Rudder = 0x0007,
+ Wheel = 0x0008,
+ Gas = 0x0009,
+ Brake = 0x000A,
+ Hat0x = 0x0010,
+ Hat0y = 0x0011,
+ Hat1x = 0x0012,
+ Hat1y = 0x0013,
+ Hat2x = 0x0014,
+ Hat2y = 0x0015,
+ Hat3x = 0x0016,
+ Hat3y = 0x0017,
+ Pressure = 0x0018,
+ Distance = 0x0019,
+ TiltX = 0x001A,
+ TiltY = 0x001B,
+ ToolWidth = 0x001C,
+ Volume = 0x0020,
+ Misc = 0x0028,
+ MtSlot = 0x002F,
+ MtTouchMajor = 0x0030,
+ MtTouchMinor = 0x0031,
+ MtWidthMajor = 0x0032,
+ MtWidthMinor = 0x0033,
+ MtOrientation = 0x0034,
+ MtPositionX = 0x0035,
+ MtPositionY = 0x0036,
+ MtToolType = 0x0037,
+ MtBlobId = 0x0038,
+ MtTrackingId = 0x0039,
+ MtPressure = 0x003A,
+ MtDistance = 0x003B,
+ MtToolX = 0x003C,
+ MtToolY = 0x003D,
+ Max = 0x003F,
+ }
+ public enum SwType : uint {
+ Lid = 0x0000,
+ TabletMode = 0x0001,
+ HeadphoneInsert = 0x0002,
+ RfkillAll = 0x0003,
+ MicrophoneInsert = 0x0004,
+ Dock = 0x0005,
+ LineoutInsert = 0x0006,
+ JackPhysicalInsert = 0x0007,
+ VideooutInsert = 0x0008,
+ CameraLensCover = 0x0009,
+ KeypadSlide = 0x000A,
+ FrontProximity = 0x000B,
+ RotateLock = 0x000C,
+ LineinInsert = 0x000D,
+ MuteDevice = 0x000E,
+ PenInserted = 0x000F,
+ Max = 0x000F,
+ }
+ public enum MscType : uint {
+ Serial = 0x0000,
+ Pulseled = 0x0001,
+ Gesture = 0x0002,
+ Raw = 0x0003,
+ Scan = 0x0004,
+ Timestamp = 0x0005,
+ Max = 0x0007,
+ }
+ public enum LedType : uint {
+ Numl = 0x0000,
+ Capsl = 0x0001,
+ Scrolll = 0x0002,
+ Compose = 0x0003,
+ Kana = 0x0004,
+ Sleep = 0x0005,
+ Suspend = 0x0006,
+ Mute = 0x0007,
+ Misc = 0x0008,
+ Mail = 0x0009,
+ Charging = 0x000A,
+ Max = 0x000F,
+ }
+ public enum RepType : uint {
+ Delay = 0x0000,
+ Period = 0x0001,
+ Max = 0x0001,
+ }
+ public enum SndType : uint {
+ Click = 0x0000,
+ Bell = 0x0001,
+ Tone = 0x0002,
+ Max = 0x0007,
+ }
+}
+
ctx = CreateContext(dpy, currentCfg, IntPtr.Zero, contextAttrib);
if (ctx == IntPtr.Zero)
throw new NotSupportedException(String.Format("[EGL] Failed to create egl context, error {0}.", GetError()));
-
-// int[] attribs = new int[] {
-// (int)Attribute.BufferSize,
-// Egl.RED_SIZE,
-// Egl.GREEN_SIZE,
-// Egl.BLUE_SIZE,
-// Egl.ALPHA_SIZE,
-// (int)Attribute.DepthSize,
-// //(int)Attribute.Height,
-// Egl.WIDTH,
-// (int)Attribute.Width,
-// (int)Attribute.Samples,
-// (int)Attribute.SampleBuffers,
-// (int)Attribute.RenderableType,
-// (int)Attribute.SurfaceType,
-// (int)Attribute.Level,
-// (int)Attribute.ConfigCaveat,
-// };
-//
-// for (int i = 0; i < configs.Length; i++) {
-// IntPtr conf = configs[i];
-// Console.Write ("{0,-3}:", i);
-// for (int j = 0; j < attribs.Length; j++) {
-// int value;
-// GetConfigAttrib (dpy, conf, attribs[j], out value);
-// Console.Write ("\t{0} = {1}, ", EglConstToString ((int)attribs[j]), value);
-// }
-// Console.Write ("\n");
-// }
-
}
#endregion
+ public IntPtr GetConfig (int[] desiredCfg){
+ int num_configs;
+ IntPtr[] configs = new IntPtr[1];
+ if (!ChooseConfig(dpy, desiredCfg, configs, 1, out num_configs)||num_configs<1)
+ throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError()));
+ return configs [0];
+ }
+ public IntPtr[] GetAllConfigs (){
+ int num_configs;
+ int[] desiredConfig = new int[]
+ {
+ Egl.SURFACE_TYPE, Egl.PBUFFER_BIT,
+ Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT,
+ Egl.NONE
+ };
+
+ if (!ChooseConfig(dpy, desiredConfig, null, 0, out num_configs)||num_configs==0)
+ throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError()));
+
+ IntPtr[] configs = new IntPtr[num_configs];
+ if (!ChooseConfig(dpy, null, configs, num_configs, out num_configs))
+ throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError()));
+ return configs;
+ }
+ public void DumpAllConf(){
+ Console.Write ("EGL Configs");
+ IntPtr[] configs = GetAllConfigs();
+ int[] attribs = new int[] {
+ (int)Attribute.BufferSize,
+ Egl.RED_SIZE,
+ Egl.GREEN_SIZE,
+ Egl.BLUE_SIZE,
+ Egl.ALPHA_SIZE,
+ (int)Attribute.DepthSize,
+ //(int)Attribute.Height,
+ Egl.WIDTH,
+ (int)Attribute.Width,
+ (int)Attribute.Samples,
+ (int)Attribute.SampleBuffers,
+ (int)Attribute.RenderableType,
+ (int)Attribute.SurfaceType,
+ (int)Attribute.Level,
+ (int)Attribute.ConfigCaveat,
+ };
+
+ for (int i = 0; i < configs.Length; i++) {
+ IntPtr conf = configs[i];
+ Console.Write ("{0,-3}:", i);
+ for (int j = 0; j < attribs.Length; j++) {
+ int value;
+ GetConfigAttrib (dpy, conf, attribs[j], out value);
+ Console.Write ("\t{0} = {1}, ", EglConstToString ((int)attribs[j]), value);
+ }
+ Console.Write ("\n");
+ }
+ }
enum ConfigAttribute {
RedSize ,
GreenSize,
if (!Context.MakeCurrent (dpy, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
Console.WriteLine ("egl clear current ctx failed");
}
- public void DestroyContext (){
- try {
- if (ctx != IntPtr.Zero)
- DestroyContext (dpy, ctx);
- } catch (Exception ex) {
- Console.WriteLine ("error disposing egl context: {0}", ex.ToString ());
- }finally {
- ctx = IntPtr.Zero;
- }
- }
#region IDisposable implementation
~Context(){
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing){
- if (dpy != IntPtr.Zero)
- Terminate (dpy);
+ try {
+ if (ctx != IntPtr.Zero)
+ DestroyContext (dpy, ctx);
+ if (dpy != IntPtr.Zero)
+ Terminate (dpy);
+ } catch (Exception ex) {
+ Console.WriteLine ("error disposing egl context: {0}", ex.ToString ());
+ }finally {
+ ctx = IntPtr.Zero;
+ dpy = IntPtr.Zero;
+ }
}
#endregion
Context ctx;
internal EGLSurface handle;
+ Surface (Context _ctx, IntPtr config, int[] attrib_list){
+ ctx = _ctx;
+ handle = eglCreatePbufferSurface (ctx.dpy, config, attrib_list);
+ if (handle == IntPtr.Zero)
+ throw new NotSupportedException(String.Format("[EGL] Failed to create surface, error {0}.", EGL.Context.GetError()));
+ }
public Surface (Context _ctx, Linux.GBM.Surface gbmSurf)
{
ctx = _ctx;
if (handle == IntPtr.Zero)
throw new NotSupportedException(String.Format("[EGL] Failed to create surface, error {0}.", EGL.Context.GetError()));
}
+ public static Surface CreatePBuffer (Context _ctx, int _width, int _height){
+ int[] config = new int[]
+ {
+ Egl.SURFACE_TYPE, Egl.PBUFFER_BIT,
+// Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT,
+// Egl.RED_SIZE, 8,
+// Egl.GREEN_SIZE, 8,
+// Egl.BLUE_SIZE, 8,
+ Egl.NONE
+ };
+ int[] attribs = new int[]
+ {
+ Egl.WIDTH, _width,
+ Egl.HEIGHT, _height,
+ Egl.NONE
+ };
+ IntPtr cfg = _ctx.GetConfig (config);
+ Console.WriteLine ("pbuff cfg: {0}", cfg.ToString ());
+ return new Surface (_ctx, cfg, attribs);
+ }
public void MakeCurrent (){
if (!Context.MakeCurrent(ctx.dpy, handle, handle, ctx.ctx))
+++ /dev/null
-#region License
-//
-// Evdev.cs
-//
-// Author:
-// Stefanos A. <stapostol@gmail.com>
-//
-// Copyright (c) 2006-2014
-//
-// 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.
-//
-using OpenTK;
-using Linux;
-using Crow;
-
-
-#endregion
-
-using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace Linux
-{
- // Bindings for linux/input.h
- class Evdev
- {
- public const int KeyCount = 0x300;
- public const int AxisCount = 0x40;
- public const int EventCount = (int)EvdevType.CNT;
-
- #region KeyMap
-
- public static readonly Key[] KeyMap = new Key[]
- {
- // 0-7
- Key.Unknown,
- Key.Escape,
- Key.Number1,
- Key.Number2,
- Key.Number3,
- Key.Number4,
- Key.Number5,
- Key.Number6,
- // 8-15
- Key.Number7,
- Key.Number8,
- Key.Number9,
- Key.Number0,
- Key.Minus,
- Key.Plus,
- Key.BackSpace,
- Key.Tab,
- // 16-23
- Key.Q,
- Key.W,
- Key.E,
- Key.R,
- Key.T,
- Key.Y,
- Key.U,
- Key.I,
- // 24-31
- Key.O,
- Key.P,
- Key.BracketLeft,
- Key.BracketRight,
- Key.Enter,
- Key.ControlLeft,
- Key.A,
- Key.S,
- // 32-39
- Key.D,
- Key.F,
- Key.G,
- Key.H,
- Key.J,
- Key.K,
- Key.L,
- Key.Semicolon,
- // 40-47
- Key.Quote,
- Key.Tilde,
- Key.ShiftLeft,
- Key.BackSlash, //Key.Execute,
- Key.Z,
- Key.X,
- Key.C,
- Key.V, //Key.Help,
- // 48-55
- Key.B,
- Key.N,
- Key.M,
- Key.Comma,
- Key.Period,
- Key.Slash,
- Key.ShiftRight,
- Key.KeypadMultiply,
- // 56-63
- Key.AltLeft,
- Key.Space,
- Key.CapsLock,
- Key.F1,
- Key.F2,
- Key.F3,
- Key.F4,
- Key.F5,
- // 64-71
- Key.F6,
- Key.F7,
- Key.F8,
- Key.F9,
- Key.F10,
- Key.NumLock,
- Key.ScrollLock,
- Key.Keypad7,
- // 72-79
- Key.Keypad8,
- Key.Keypad9,
- Key.KeypadSubtract,
- Key.Keypad4,
- Key.Keypad5,
- Key.Keypad6,
- Key.KeypadPlus,
- Key.Keypad1,
- // 80-87
- Key.Keypad2,
- Key.Keypad3,
- Key.Keypad0,
- Key.KeypadPeriod,
- Key.Unknown,
- Key.Unknown, // zenkakuhankaku
- Key.Unknown, // 102ND
- Key.F11,
- // 88-95
- Key.F12,
- Key.Unknown, // ro
- Key.Unknown, // katakana
- Key.Unknown, // hiragana
- Key.Unknown, // henkan
- Key.Unknown, // katakanahiragana
- Key.Unknown, // muhenkan
- Key.Unknown, // kpjpcomma
- // 96-103
- Key.KeypadEnter,
- Key.ControlRight,
- Key.KeypadDivide,
- Key.Unknown, // sysrq
- Key.AltRight,
- Key.Unknown, // linefeed
- Key.Home,
- Key.Up,
- // 104-111
- Key.PageUp,
- Key.Left,
- Key.Right,
- Key.End,
- Key.Down,
- Key.PageDown,
- Key.Insert,
- Key.Delete,
- // 112-119
- Key.Unknown, // macro
- Key.Unknown, // mute
- Key.Unknown, // volumedown
- Key.Unknown, // volumeup
- Key.Unknown, // power
- Key.Unknown, // kpequal
- Key.Unknown, // kpplusminus
- Key.Pause,
- // 120-127
- Key.Unknown, // scale
- Key.Unknown, // kpcomma
- Key.Unknown, // hangeul / hanguel
- Key.Unknown, // hanja
- Key.Unknown, // yen
- Key.WinLeft,
- Key.WinRight,
- Key.Unknown, // compose
- // 128-135
- Key.Unknown, // stop
- Key.Unknown, // again
- Key.Unknown, // props
- Key.Unknown, // undo
- Key.Unknown, // front
- Key.Unknown, // copy
- Key.Unknown, // open
- Key.Unknown, // paste
- // 136-143
- Key.Unknown, // find
- Key.Unknown, // cut
- Key.Unknown, // help
- Key.Unknown, // menu
- Key.Unknown, // calc
- Key.Unknown, // setup
- Key.Unknown, // sleep
- Key.Unknown, // wakeup
- // 144-151
- Key.Unknown, // file
- Key.Unknown, // send file
- Key.Unknown, // delete file
- Key.Unknown, // xfer
- Key.Unknown, // prog1
- Key.Unknown, // prog2
- Key.Unknown, // www
- Key.Unknown, // msdos
- // 152-159
- Key.Unknown, // coffee / screenlock
- Key.Unknown, // direction
- Key.Unknown, // cycle windows
- Key.Unknown, // mail
- Key.Unknown, // bookmarks
- Key.Unknown, // computer
- Key.Back,
- Key.Unknown, // forward
- // 160-167
- Key.Unknown, // close cd
- Key.Unknown, // eject cd
- Key.Unknown, // eject/close cd
- Key.Unknown, // next song
- Key.Unknown, // play/pause
- Key.Unknown, // previous song
- Key.Unknown, // stop cd
- Key.Unknown, // record
- // 168-175
- Key.Unknown, // rewind
- Key.Unknown, // phone
- Key.Unknown, // iso
- Key.Unknown, // config
- Key.Unknown, // homepage
- Key.Unknown, // refresh
- Key.Unknown, // exit
- Key.Unknown, // move,
- // 176-183
- Key.Unknown, // edit,
- Key.Unknown, // scroll up,
- Key.Unknown, // scroll down,
- Key.Unknown, // kp left paren,
- Key.Unknown, // kp right paren,
- Key.Unknown, // new,
- Key.Unknown, // redo,
- Key.F13,
- // 184-191
- Key.F14,
- Key.F15,
- Key.F16,
- Key.F17,
- Key.F18,
- Key.F19,
- Key.F20,
- Key.F21,
- // 192-199
- Key.F22,
- Key.F23,
- Key.F24,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- // 200-207
- Key.Unknown, // play cd
- Key.Unknown, // pause cd
- Key.Unknown, // prog3
- Key.Unknown, // prog4
- Key.Unknown, // dashboard
- Key.Unknown, // suspend
- Key.Unknown, // close
- Key.Unknown, // play
- // 208-215
- Key.Unknown, // fast forward
- Key.Unknown, // bass boost
- Key.Unknown, // print
- Key.Unknown, // hp
- Key.Unknown, // camera
- Key.Unknown, // sound
- Key.Unknown, // question
- Key.Unknown, // email
- // 216-223
- Key.Unknown, // chat
- Key.Unknown, // search
- Key.Unknown, // connect
- Key.Unknown, // finance
- Key.Unknown, // sport
- Key.Unknown, // shop
- Key.Unknown, // alt erase
- Key.Unknown, // cancel
- // 224-231
- Key.Unknown, // brightness down
- Key.Unknown, // brightness up
- Key.Unknown, // media
- Key.Unknown, // switch video mode
- Key.Unknown, // dillum toggle
- Key.Unknown, // dillum down
- Key.Unknown, // dillum up
- Key.Unknown, // send
- // 232-239
- Key.Unknown, // reply
- Key.Unknown, // forward email
- Key.Unknown, // save
- Key.Unknown, // documents
- Key.Unknown, // battery
- Key.Unknown, // bluetooth
- Key.Unknown, // wlan
- Key.Unknown, // uwb
- // 240-247
- Key.Unknown,
- Key.Unknown, // video next
- Key.Unknown, // video prev
- Key.Unknown, // brightness cycle
- Key.Unknown, // brightness zero
- Key.Unknown, // display off
- Key.Unknown, // wwan / wimax
- Key.Unknown, // rfkill
- // 248-255
- Key.Unknown, // mic mute
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown,
- Key.Unknown, // reserved
- };
-
- #endregion
-
- public static MouseButton GetMouseButton(EvdevButton button)
- {
- switch (button)
- {
- case EvdevButton.LEFT:
- return MouseButton.Left;
- case EvdevButton.RIGHT:
- return MouseButton.Right;
- case EvdevButton.MIDDLE:
- return MouseButton.Middle;
- case EvdevButton.BTN0:
- return MouseButton.Button1;
- case EvdevButton.BTN1:
- return MouseButton.Button2;
- case EvdevButton.BTN2:
- return MouseButton.Button3;
- case EvdevButton.BTN3:
- return MouseButton.Button4;
- case EvdevButton.BTN4:
- return MouseButton.Button5;
- case EvdevButton.BTN5:
- return MouseButton.Button6;
- case EvdevButton.BTN6:
- return MouseButton.Button7;
- case EvdevButton.BTN7:
- return MouseButton.Button8;
- case EvdevButton.BTN8:
- return MouseButton.Button9;
- default:
- Debug.Print("[Input] Unknown EvdevButton {0}", button);
- return MouseButton.Left;
- }
- }
-
- static uint IOCreate(DirectionFlags dir, int number, int length)
- {
- long v =
- ((byte)dir << 30) |
- ((byte)'E' << 8) |
- (number << 0) |
- (length << 16);
- return (uint)v;
- }
-
- // Get absolute value / limits
- public static int GetAbs(int fd, EvdevAxis axis, out InputAbsInfo info)
- {
- info = default(InputAbsInfo);
- unsafe
- {
- fixed (InputAbsInfo* pinfo = &info)
- {
- // EVIOCGABS(abs) = _IOR('E', 0x40 + (abs), struct input_absinfo)
- uint ioctl = IOCreate(DirectionFlags.Read, (int)axis + 0x40, BlittableValueType<InputAbsInfo>.Stride);
- int retval = Libc.ioctl(fd, ioctl, new IntPtr(pinfo));
- return retval;
- }
- }
- }
-
- // Get supported event bits
- public static int GetBit(int fd, EvdevType ev, int length, IntPtr data)
- {
- // EVIOCGBIT = _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
- uint ioctl = IOCreate(DirectionFlags.Read, (int)ev + 0x20, length);
- int retval = Libc.ioctl(fd, ioctl, data);
- return retval;
- }
-
- public static int GetName(int fd, out string name)
- {
- unsafe
- {
- sbyte* pname = stackalloc sbyte[129];
- int ret = Libc.ioctl(fd, EvdevIoctl.Name128, new IntPtr(pname));
- name = new string(pname);
- return ret;
- }
- }
-
- public static int GetId(int fd, out EvdevInputId id)
- {
- id = default(EvdevInputId);
- unsafe
- {
- fixed (EvdevInputId* pid = &id)
- {
- return Libc.ioctl(fd, EvdevIoctl.Id, new IntPtr(pid));
- }
- }
- }
- }
-
- enum EvdevAxis
- {
- X = 0x00,
- Y = 0x01,
- Z = 0x02,
- RX = 0x03,
- RY = 0x04,
- RZ = 0x05,
- THROTTLE = 0x06,
- RUDDER = 0x07,
- WHEEL = 0x08,
- GAS = 0x09,
- BRAKE = 0x0a,
- HAT0X = 0x10,
- HAT0Y = 0x11,
- HAT1X = 0x12,
- HAT1Y = 0x13,
- HAT2X = 0x14,
- HAT2Y = 0x15,
- HAT3X = 0x16,
- HAT3Y = 0x17,
- PRESSURE = 0x18,
- DISTANCE = 0x19,
- TILT_X = 0x1a,
- TILT_Y = 0x1b,
- TOOL_WIDTH = 0x1c,
-
- VOLUME = 0x20,
-
- MISC = 0x28,
-
- MT_SLOT = 0x2f, /* MT slot being modified */
- MT_TOUCH_MAJOR = 0x30, /* Major axis of touching ellipse */
- MT_TOUCH_MINOR = 0x31, /* Minor axis (omit if circular) */
- MT_WIDTH_MAJOR = 0x32, /* Major axis of approaching ellipse */
- MT_WIDTH_MINOR = 0x33, /* Minor axis (omit if circular) */
- MT_ORIENTATION = 0x34, /* Ellipse orientation */
- MT_POSITION_X = 0x35, /* Center X touch position */
- MT_POSITION_Y = 0x36, /* Center Y touch position */
- MT_TOOL_TYPE = 0x37, /* Type of touching device */
- MT_BLOB_ID = 0x38, /* Group a set of packets as a blob */
- MT_TRACKING_ID = 0x39, /* Unique ID of initiated contact */
- MT_PRESSURE = 0x3a, /* Pressure on contact area */
- MT_DISTANCE = 0x3b, /* Contact hover distance */
- MT_TOOL_X = 0x3c, /* Center X tool position */
- MT_TOOL_Y = 0x3d, /* Center Y tool position */
-
- MAX = 0x3f,
- CNT = (MAX+1),
- }
-
- enum EvdevButton
- {
- MISC = 0x100,
- BTN0 = 0x100,
- BTN1 = 0x101,
- BTN2 = 0x102,
- BTN3 = 0x103,
- BTN4 = 0x104,
- BTN5 = 0x105,
- BTN6 = 0x106,
- BTN7 = 0x107,
- BTN8 = 0x108,
- BTN9 = 0x109,
-
- MOUSE = 0x110,
- LEFT = 0x110,
- RIGHT = 0x111,
- MIDDLE = 0x112,
- SIDE = 0x113,
- EXTRA = 0x114,
- FORWARD = 0x115,
- BACK = 0x116,
- TASK = 0x117,
-
- JOYSTICK = 0x120,
- TRIGGER = 0x120,
- THUMB = 0x121,
- THUMB2 = 0x122,
- TOP = 0x123,
- TOP2 = 0x124,
- PINKIE = 0x125,
- BASE = 0x126,
- BASE2 = 0x127,
- BASE3 = 0x128,
- BASE4 = 0x129,
- BASE5 = 0x12a,
- BASE6 = 0x12b,
- DEAD = 0x12f,
-
- GAMEPAD = 0x130,
- SOUTH = 0x130,
- A = SOUTH,
- EAST = 0x131,
- B = EAST,
- C = 0x132,
- NORTH = 0x133,
- X = NORTH,
- WEST = 0x134,
- Y = WEST,
- Z = 0x135,
- TL = 0x136,
- TR = 0x137,
- TL2 = 0x138,
- TR2 = 0x139,
- SELECT = 0x13a,
- START = 0x13b,
- MODE = 0x13c,
- THUMBL = 0x13d,
- THUMBR = 0x13e,
-
- DIGI = 0x140,
- TOOL_PEN = 0x140,
- TOOL_RUBBER = 0x141,
- TOOL_BRUSH = 0x142,
- TOOL_PENCIL = 0x143,
- TOOL_AIRBRUSH = 0x144,
- TOOL_FINGER = 0x145,
- TOOL_MOUSE = 0x146,
- TOOL_LENS = 0x147,
- TOOL_QUINTTAP = 0x148, // Five fingers on trackpad
- TOUCH = 0x14a,
- STYLUS = 0x14b,
- STYLUS2 = 0x14c,
- TOOL_DOUBLETAP = 0x14d,
- TOOL_TRIPLETAP = 0x14e,
- TOOL_QUADTAP = 0x14f, // Four fingers on trackpad
-
- WHEEL = 0x150,
- GEAR_DOWN = 0x150,
- GEAR_UP = 0x151,
-
- DPAD_UP = 0x220,
- DPAD_DOWN = 0x221,
- DPAD_LEFT = 0x222,
- DPAD_RIGHT = 0x223,
-
- Last = 0x300,
- }
-
- enum EvdevType : byte
- {
- SYN = 0x00,
- KEY = 0x01,
- REL = 0x02,
- ABS = 0x03,
- MSC = 0x04,
- SW = 0x05,
- LED = 0x11,
- SND = 0x12,
- REP = 0x14,
- FF = 0x15,
- PWR = 0x16,
- FF_STATUS = 0x17,
- MAX = 0x1f,
- CNT = (MAX+1),
- }
-
- enum EvdevIoctl : uint
- {
- Id = (2u << 30) | ((byte)'E' << 8) | (0x02u << 0) | (8u << 16), //EVIOCGID = _IOR('E', 0x02, struct input_id)
- Name128 = (2u << 30) | ((byte)'E' << 8) | (0x06u << 0) | (128u << 16), //EVIOCGNAME(len) = _IOC(_IOC_READ, 'E', 0x06, len)
- }
-
- [StructLayout(LayoutKind.Sequential)]
- struct InputAbsInfo
- {
- public int Value;
- public int Minimum;
- public int Maximum;
- public int Fuzz;
- public int Flat;
- public int Resolution;
- };
-
- [StructLayout(LayoutKind.Sequential)]
- struct InputId
- {
- public ushort BusType;
- public ushort Vendor;
- public ushort Product;
- public ushort Version;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- struct InputEvent
- {
- public TimeVal Time;
- ushort type;
- public ushort Code;
- public int Value;
-
- public EvdevType Type { get { return (EvdevType)type; } }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- struct TimeVal
- {
- public IntPtr Seconds;
- public IntPtr MicroSeconds;
- }
-}
-
--- /dev/null
+#region License
+//
+// Evdev.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014
+//
+// 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.
+//
+using OpenTK;
+using Linux;
+using Crow;
+
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Linux.oldEvDev
+{
+ // Bindings for linux/input.h
+ class EvdevClass
+ {
+
+ public const int KeyCount = 0x300;
+ public const int AxisCount = 0x40;
+ public const int EventCount = (int)EvdevType.CNT;
+
+ #region KeyMap
+
+ public static readonly Key[] KeyMap = new Key[]
+ {
+ // 0-7
+ Key.Unknown,
+ Key.Escape,
+ Key.Number1,
+ Key.Number2,
+ Key.Number3,
+ Key.Number4,
+ Key.Number5,
+ Key.Number6,
+ // 8-15
+ Key.Number7,
+ Key.Number8,
+ Key.Number9,
+ Key.Number0,
+ Key.Minus,
+ Key.Plus,
+ Key.BackSpace,
+ Key.Tab,
+ // 16-23
+ Key.Q,
+ Key.W,
+ Key.E,
+ Key.R,
+ Key.T,
+ Key.Y,
+ Key.U,
+ Key.I,
+ // 24-31
+ Key.O,
+ Key.P,
+ Key.BracketLeft,
+ Key.BracketRight,
+ Key.Enter,
+ Key.ControlLeft,
+ Key.A,
+ Key.S,
+ // 32-39
+ Key.D,
+ Key.F,
+ Key.G,
+ Key.H,
+ Key.J,
+ Key.K,
+ Key.L,
+ Key.Semicolon,
+ // 40-47
+ Key.Quote,
+ Key.Tilde,
+ Key.ShiftLeft,
+ Key.BackSlash, //Key.Execute,
+ Key.Z,
+ Key.X,
+ Key.C,
+ Key.V, //Key.Help,
+ // 48-55
+ Key.B,
+ Key.N,
+ Key.M,
+ Key.Comma,
+ Key.Period,
+ Key.Slash,
+ Key.ShiftRight,
+ Key.KeypadMultiply,
+ // 56-63
+ Key.AltLeft,
+ Key.Space,
+ Key.CapsLock,
+ Key.F1,
+ Key.F2,
+ Key.F3,
+ Key.F4,
+ Key.F5,
+ // 64-71
+ Key.F6,
+ Key.F7,
+ Key.F8,
+ Key.F9,
+ Key.F10,
+ Key.NumLock,
+ Key.ScrollLock,
+ Key.Keypad7,
+ // 72-79
+ Key.Keypad8,
+ Key.Keypad9,
+ Key.KeypadSubtract,
+ Key.Keypad4,
+ Key.Keypad5,
+ Key.Keypad6,
+ Key.KeypadPlus,
+ Key.Keypad1,
+ // 80-87
+ Key.Keypad2,
+ Key.Keypad3,
+ Key.Keypad0,
+ Key.KeypadPeriod,
+ Key.Unknown,
+ Key.Unknown, // zenkakuhankaku
+ Key.Unknown, // 102ND
+ Key.F11,
+ // 88-95
+ Key.F12,
+ Key.Unknown, // ro
+ Key.Unknown, // katakana
+ Key.Unknown, // hiragana
+ Key.Unknown, // henkan
+ Key.Unknown, // katakanahiragana
+ Key.Unknown, // muhenkan
+ Key.Unknown, // kpjpcomma
+ // 96-103
+ Key.KeypadEnter,
+ Key.ControlRight,
+ Key.KeypadDivide,
+ Key.Unknown, // sysrq
+ Key.AltRight,
+ Key.Unknown, // linefeed
+ Key.Home,
+ Key.Up,
+ // 104-111
+ Key.PageUp,
+ Key.Left,
+ Key.Right,
+ Key.End,
+ Key.Down,
+ Key.PageDown,
+ Key.Insert,
+ Key.Delete,
+ // 112-119
+ Key.Unknown, // macro
+ Key.Unknown, // mute
+ Key.Unknown, // volumedown
+ Key.Unknown, // volumeup
+ Key.Unknown, // power
+ Key.Unknown, // kpequal
+ Key.Unknown, // kpplusminus
+ Key.Pause,
+ // 120-127
+ Key.Unknown, // scale
+ Key.Unknown, // kpcomma
+ Key.Unknown, // hangeul / hanguel
+ Key.Unknown, // hanja
+ Key.Unknown, // yen
+ Key.WinLeft,
+ Key.WinRight,
+ Key.Unknown, // compose
+ // 128-135
+ Key.Unknown, // stop
+ Key.Unknown, // again
+ Key.Unknown, // props
+ Key.Unknown, // undo
+ Key.Unknown, // front
+ Key.Unknown, // copy
+ Key.Unknown, // open
+ Key.Unknown, // paste
+ // 136-143
+ Key.Unknown, // find
+ Key.Unknown, // cut
+ Key.Unknown, // help
+ Key.Unknown, // menu
+ Key.Unknown, // calc
+ Key.Unknown, // setup
+ Key.Unknown, // sleep
+ Key.Unknown, // wakeup
+ // 144-151
+ Key.Unknown, // file
+ Key.Unknown, // send file
+ Key.Unknown, // delete file
+ Key.Unknown, // xfer
+ Key.Unknown, // prog1
+ Key.Unknown, // prog2
+ Key.Unknown, // www
+ Key.Unknown, // msdos
+ // 152-159
+ Key.Unknown, // coffee / screenlock
+ Key.Unknown, // direction
+ Key.Unknown, // cycle windows
+ Key.Unknown, // mail
+ Key.Unknown, // bookmarks
+ Key.Unknown, // computer
+ Key.Back,
+ Key.Unknown, // forward
+ // 160-167
+ Key.Unknown, // close cd
+ Key.Unknown, // eject cd
+ Key.Unknown, // eject/close cd
+ Key.Unknown, // next song
+ Key.Unknown, // play/pause
+ Key.Unknown, // previous song
+ Key.Unknown, // stop cd
+ Key.Unknown, // record
+ // 168-175
+ Key.Unknown, // rewind
+ Key.Unknown, // phone
+ Key.Unknown, // iso
+ Key.Unknown, // config
+ Key.Unknown, // homepage
+ Key.Unknown, // refresh
+ Key.Unknown, // exit
+ Key.Unknown, // move,
+ // 176-183
+ Key.Unknown, // edit,
+ Key.Unknown, // scroll up,
+ Key.Unknown, // scroll down,
+ Key.Unknown, // kp left paren,
+ Key.Unknown, // kp right paren,
+ Key.Unknown, // new,
+ Key.Unknown, // redo,
+ Key.F13,
+ // 184-191
+ Key.F14,
+ Key.F15,
+ Key.F16,
+ Key.F17,
+ Key.F18,
+ Key.F19,
+ Key.F20,
+ Key.F21,
+ // 192-199
+ Key.F22,
+ Key.F23,
+ Key.F24,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ // 200-207
+ Key.Unknown, // play cd
+ Key.Unknown, // pause cd
+ Key.Unknown, // prog3
+ Key.Unknown, // prog4
+ Key.Unknown, // dashboard
+ Key.Unknown, // suspend
+ Key.Unknown, // close
+ Key.Unknown, // play
+ // 208-215
+ Key.Unknown, // fast forward
+ Key.Unknown, // bass boost
+ Key.Unknown, // print
+ Key.Unknown, // hp
+ Key.Unknown, // camera
+ Key.Unknown, // sound
+ Key.Unknown, // question
+ Key.Unknown, // email
+ // 216-223
+ Key.Unknown, // chat
+ Key.Unknown, // search
+ Key.Unknown, // connect
+ Key.Unknown, // finance
+ Key.Unknown, // sport
+ Key.Unknown, // shop
+ Key.Unknown, // alt erase
+ Key.Unknown, // cancel
+ // 224-231
+ Key.Unknown, // brightness down
+ Key.Unknown, // brightness up
+ Key.Unknown, // media
+ Key.Unknown, // switch video mode
+ Key.Unknown, // dillum toggle
+ Key.Unknown, // dillum down
+ Key.Unknown, // dillum up
+ Key.Unknown, // send
+ // 232-239
+ Key.Unknown, // reply
+ Key.Unknown, // forward email
+ Key.Unknown, // save
+ Key.Unknown, // documents
+ Key.Unknown, // battery
+ Key.Unknown, // bluetooth
+ Key.Unknown, // wlan
+ Key.Unknown, // uwb
+ // 240-247
+ Key.Unknown,
+ Key.Unknown, // video next
+ Key.Unknown, // video prev
+ Key.Unknown, // brightness cycle
+ Key.Unknown, // brightness zero
+ Key.Unknown, // display off
+ Key.Unknown, // wwan / wimax
+ Key.Unknown, // rfkill
+ // 248-255
+ Key.Unknown, // mic mute
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown,
+ Key.Unknown, // reserved
+ };
+
+ #endregion
+
+ public static MouseButton GetMouseButton(EvdevButton button)
+ {
+ switch (button)
+ {
+ case EvdevButton.LEFT:
+ return MouseButton.Left;
+ case EvdevButton.RIGHT:
+ return MouseButton.Right;
+ case EvdevButton.MIDDLE:
+ return MouseButton.Middle;
+ case EvdevButton.BTN0:
+ return MouseButton.Button1;
+ case EvdevButton.BTN1:
+ return MouseButton.Button2;
+ case EvdevButton.BTN2:
+ return MouseButton.Button3;
+ case EvdevButton.BTN3:
+ return MouseButton.Button4;
+ case EvdevButton.BTN4:
+ return MouseButton.Button5;
+ case EvdevButton.BTN5:
+ return MouseButton.Button6;
+ case EvdevButton.BTN6:
+ return MouseButton.Button7;
+ case EvdevButton.BTN7:
+ return MouseButton.Button8;
+ case EvdevButton.BTN8:
+ return MouseButton.Button9;
+ default:
+ Debug.Print("[Input] Unknown EvdevButton {0}", button);
+ return MouseButton.Left;
+ }
+ }
+
+ static uint IOCreate(DirectionFlags dir, int number, int length)
+ {
+ long v =
+ ((byte)dir << 30) |
+ ((byte)'E' << 8) |
+ (number << 0) |
+ (length << 16);
+ return (uint)v;
+ }
+
+ // Get absolute value / limits
+ public static int GetAbs(int fd, EvdevAxis axis, out InputAbsInfo info)
+ {
+ info = default(InputAbsInfo);
+ unsafe
+ {
+ fixed (InputAbsInfo* pinfo = &info)
+ {
+ // EVIOCGABS(abs) = _IOR('E', 0x40 + (abs), struct input_absinfo)
+ uint ioctl = IOCreate(DirectionFlags.Read, (int)axis + 0x40, BlittableValueType<InputAbsInfo>.Stride);
+ int retval = Libc.ioctl(fd, ioctl, new IntPtr(pinfo));
+ return retval;
+ }
+ }
+ }
+
+ // Get supported event bits
+ public static int GetBit(int fd, EvdevType ev, int length, IntPtr data)
+ {
+ // EVIOCGBIT = _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
+ uint ioctl = IOCreate(DirectionFlags.Read, (int)ev + 0x20, length);
+ int retval = Libc.ioctl(fd, ioctl, data);
+ return retval;
+ }
+
+ public static int GetName(int fd, out string name)
+ {
+ unsafe
+ {
+ sbyte* pname = stackalloc sbyte[129];
+ int ret = Libc.ioctl(fd, EvdevIoctl.Name128, new IntPtr(pname));
+ name = new string(pname);
+ return ret;
+ }
+ }
+
+ public static int GetId(int fd, out EvdevInputId id)
+ {
+ id = default(EvdevInputId);
+ unsafe
+ {
+ fixed (EvdevInputId* pid = &id)
+ {
+ return Libc.ioctl(fd, EvdevIoctl.Id, new IntPtr(pid));
+ }
+ }
+ }
+ }
+
+ enum EvdevAxis
+ {
+ X = 0x00,
+ Y = 0x01,
+ Z = 0x02,
+ RX = 0x03,
+ RY = 0x04,
+ RZ = 0x05,
+ THROTTLE = 0x06,
+ RUDDER = 0x07,
+ WHEEL = 0x08,
+ GAS = 0x09,
+ BRAKE = 0x0a,
+ HAT0X = 0x10,
+ HAT0Y = 0x11,
+ HAT1X = 0x12,
+ HAT1Y = 0x13,
+ HAT2X = 0x14,
+ HAT2Y = 0x15,
+ HAT3X = 0x16,
+ HAT3Y = 0x17,
+ PRESSURE = 0x18,
+ DISTANCE = 0x19,
+ TILT_X = 0x1a,
+ TILT_Y = 0x1b,
+ TOOL_WIDTH = 0x1c,
+
+ VOLUME = 0x20,
+
+ MISC = 0x28,
+
+ MT_SLOT = 0x2f, /* MT slot being modified */
+ MT_TOUCH_MAJOR = 0x30, /* Major axis of touching ellipse */
+ MT_TOUCH_MINOR = 0x31, /* Minor axis (omit if circular) */
+ MT_WIDTH_MAJOR = 0x32, /* Major axis of approaching ellipse */
+ MT_WIDTH_MINOR = 0x33, /* Minor axis (omit if circular) */
+ MT_ORIENTATION = 0x34, /* Ellipse orientation */
+ MT_POSITION_X = 0x35, /* Center X touch position */
+ MT_POSITION_Y = 0x36, /* Center Y touch position */
+ MT_TOOL_TYPE = 0x37, /* Type of touching device */
+ MT_BLOB_ID = 0x38, /* Group a set of packets as a blob */
+ MT_TRACKING_ID = 0x39, /* Unique ID of initiated contact */
+ MT_PRESSURE = 0x3a, /* Pressure on contact area */
+ MT_DISTANCE = 0x3b, /* Contact hover distance */
+ MT_TOOL_X = 0x3c, /* Center X tool position */
+ MT_TOOL_Y = 0x3d, /* Center Y tool position */
+
+ MAX = 0x3f,
+ CNT = (MAX+1),
+ }
+
+ enum EvdevButton
+ {
+ MISC = 0x100,
+ BTN0 = 0x100,
+ BTN1 = 0x101,
+ BTN2 = 0x102,
+ BTN3 = 0x103,
+ BTN4 = 0x104,
+ BTN5 = 0x105,
+ BTN6 = 0x106,
+ BTN7 = 0x107,
+ BTN8 = 0x108,
+ BTN9 = 0x109,
+
+ MOUSE = 0x110,
+ LEFT = 0x110,
+ RIGHT = 0x111,
+ MIDDLE = 0x112,
+ SIDE = 0x113,
+ EXTRA = 0x114,
+ FORWARD = 0x115,
+ BACK = 0x116,
+ TASK = 0x117,
+
+ JOYSTICK = 0x120,
+ TRIGGER = 0x120,
+ THUMB = 0x121,
+ THUMB2 = 0x122,
+ TOP = 0x123,
+ TOP2 = 0x124,
+ PINKIE = 0x125,
+ BASE = 0x126,
+ BASE2 = 0x127,
+ BASE3 = 0x128,
+ BASE4 = 0x129,
+ BASE5 = 0x12a,
+ BASE6 = 0x12b,
+ DEAD = 0x12f,
+
+ GAMEPAD = 0x130,
+ SOUTH = 0x130,
+ A = SOUTH,
+ EAST = 0x131,
+ B = EAST,
+ C = 0x132,
+ NORTH = 0x133,
+ X = NORTH,
+ WEST = 0x134,
+ Y = WEST,
+ Z = 0x135,
+ TL = 0x136,
+ TR = 0x137,
+ TL2 = 0x138,
+ TR2 = 0x139,
+ SELECT = 0x13a,
+ START = 0x13b,
+ MODE = 0x13c,
+ THUMBL = 0x13d,
+ THUMBR = 0x13e,
+
+ DIGI = 0x140,
+ TOOL_PEN = 0x140,
+ TOOL_RUBBER = 0x141,
+ TOOL_BRUSH = 0x142,
+ TOOL_PENCIL = 0x143,
+ TOOL_AIRBRUSH = 0x144,
+ TOOL_FINGER = 0x145,
+ TOOL_MOUSE = 0x146,
+ TOOL_LENS = 0x147,
+ TOOL_QUINTTAP = 0x148, // Five fingers on trackpad
+ TOUCH = 0x14a,
+ STYLUS = 0x14b,
+ STYLUS2 = 0x14c,
+ TOOL_DOUBLETAP = 0x14d,
+ TOOL_TRIPLETAP = 0x14e,
+ TOOL_QUADTAP = 0x14f, // Four fingers on trackpad
+
+ WHEEL = 0x150,
+ GEAR_DOWN = 0x150,
+ GEAR_UP = 0x151,
+
+ DPAD_UP = 0x220,
+ DPAD_DOWN = 0x221,
+ DPAD_LEFT = 0x222,
+ DPAD_RIGHT = 0x223,
+
+ Last = 0x300,
+ }
+
+ enum EvdevType : byte
+ {
+ SYN = 0x00,
+ KEY = 0x01,
+ REL = 0x02,
+ ABS = 0x03,
+ MSC = 0x04,
+ SW = 0x05,
+ LED = 0x11,
+ SND = 0x12,
+ REP = 0x14,
+ FF = 0x15,
+ PWR = 0x16,
+ FF_STATUS = 0x17,
+ MAX = 0x1f,
+ CNT = (MAX+1),
+ }
+
+ enum EvdevIoctl : uint
+ {
+ Id = (2u << 30) | ((byte)'E' << 8) | (0x02u << 0) | (8u << 16), //EVIOCGID = _IOR('E', 0x02, struct input_id)
+ Name128 = (2u << 30) | ((byte)'E' << 8) | (0x06u << 0) | (128u << 16), //EVIOCGNAME(len) = _IOC(_IOC_READ, 'E', 0x06, len)
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputAbsInfo
+ {
+ public int Value;
+ public int Minimum;
+ public int Maximum;
+ public int Fuzz;
+ public int Flat;
+ public int Resolution;
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputId
+ {
+ public ushort BusType;
+ public ushort Vendor;
+ public ushort Product;
+ public ushort Version;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct InputEvent
+ {
+ public TimeVal Time;
+ ushort type;
+ public ushort Code;
+ public int Value;
+
+ public EvdevType Type { get { return (EvdevType)type; } }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct TimeVal
+ {
+ public IntPtr Seconds;
+ public IntPtr MicroSeconds;
+ }
+}
+
public IntPtr BaseEvent { get { return GetBaseEvent(@event); } }
public IntPtr Event { get { return @event; } }
public uint Time { get { return GetTime(@event); } }
- public EvdevButton Button { get { return (EvdevButton)GetButton(@event); } }
+ public Linux.oldEvDev.EvdevButton Button { get { return (Linux.oldEvDev.EvdevButton)GetButton(@event); } }
public uint ButtonCount { get { return GetButtonCount(@event); } }
public ButtonState ButtonState { get { return GetButtonState(@event); } }
public bool HasAxis(PointerAxis axis) { return HasAxis(@event, axis) != 0; }
[DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y_transformed", CallingConvention = CallingConvention.Cdecl)]
static extern double GetAbsYTransformed(IntPtr @event, int height);
+
+ public override string ToString ()
+ {
+ return string.Format ("[PointerEvent: BaseEvent={0}, Event={1}, Time={2}, Button={3}, ButtonCount={4}, ButtonState={5}, DeltaX={6}, DeltaY={7}, X={8}, Y={9}]", BaseEvent, Event, Time, Button, ButtonCount, ButtonState, DeltaX, DeltaY, X, Y);
+ }
}
}
public static extern int ioctl(int d, JoystickIoctlCode request, StringBuilder data);
[DllImport(lib)]
- public static extern int ioctl(int d, EvdevIoctl request, [Out] IntPtr data);
+ public static extern int ioctl(int d, Linux.oldEvDev.EvdevIoctl request, [Out] IntPtr data);
[DllImport(lib)]
- public static extern int ioctl(int d, uint request, [Out] IntPtr data);
+ public static extern int ioctl(int d, uint request, [Out] IntPtr data);
+
+ [DllImport(lib)]
+ public static extern int ioctl(int d, uint request, ref Evdev.KeyMapEntry kme);
+
+ [DllImport(lib)]
+ public static extern int ioctl(int d, uint request, [In, Out] int[] data);
[DllImport(lib)]
public static extern int ioctl(int d, KeyboardIoctlCode request, ref IntPtr data);
[DllImport(lib)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool isatty(int fd);
+
+ [DllImport(lib)]
+ public static extern int getgid ();
+ [DllImport(lib)]
+ public static extern int setpgid (int pid, int pgid);
+ [DllImport(lib)]
+ public static extern int getpgid (int pid);
+
+ //public static extern int setpgrp (int pgid);
+ [DllImport(lib)]
+ public static extern int getpgrp ();
}
enum ErrorNumber
// FLAG_3D_L_DEPTH (5<<14)
// FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14)
// FLAG_3D_TOP_AND_BOTTOM (7<<14)
- // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
+ // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
}
#endregion
int fd_gpu = -1;
GBM.Device gbmDev;
GBM.Surface gbmSurf;
- EGL.Context eglctx;
+ public EGL.Context eglctx;
EGL.Surface eglSurf;
Cairo.EGLDevice cairoDev;
fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
if (fd_gpu < 0)
throw new NotSupportedException("[DRI] Failed to open gpu");
-
+
resources = new Resources (fd_gpu);
gbmDev = new GBM.Device (fd_gpu);
eglctx = new EGL.Context (gbmDev);
try {
if (defaultConfiguration ())
- Console.WriteLine ("default config ok");
+ Console.WriteLine ("default config ok");
} catch (Exception ex) {
Console.WriteLine (ex.ToString());
}
if (c.State == ConnectionStatus.Connected) {
connector = c;
break;
- }
+ }
}
if (connector == null)
return false;
-
+
currentCrtc = connector.CurrentEncoder.CurrentCrtc;
originalMode = currentCrtc.CurrentMode;
originalFB = currentCrtc.CurrentFbId;
//currentMode = originalMode;
currentMode = getNewMode();
- //setScanOutRegion();
-
//configure a rendering stack
gbmSurf = new GBM.Surface (gbmDev, Width, Height,
GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout);
CairoSurf = new Cairo.GLSurface (cairoDev, eglSurf.handle, Width, Height);
//cairoSurf = new Cairo.EGLSurface (cairoDev, egl_surface, 1600, 900);
- cairoDev.SetThreadAware (false);
+ cairoDev.SetThreadAware (true);
if (cairoDev.Acquire () != Cairo.Status.Success)
Console.WriteLine ("[Cairo]: Failed to acquire egl device.");
}
}
+ unsafe GBM.gbm_bo* bo;
+ uint fb;
-
-
unsafe public void Update(){
- GBM.gbm_bo* bo;
- uint fb;
-
+ int ret = 0;
if (!gbmSurf.HasFreeBuffers)
throw new NotSupportedException("[GBM] Out of free buffer");
-
bo = gbmSurf.Lock ();
- int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
- if (ret != 0)
- Console.WriteLine ("addFb failed: {0}", ret);
- bo->SetUserData (ref fb, handleDestroyFB);
-
+ if (fb == 0) {
+ ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ }
uint connId = connector.Id;
ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
if (ret != 0)
Console.WriteLine ("setCrtc failed: {0}", ret);
-
gbmSurf.Release (bo);
}
evctx.version = EventContext.Version;
evctx.page_flip_handler = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip);
}
- unsafe GBM.gbm_bo* bo;
unsafe public void UpdateWithPageFlip(){
- GBM.gbm_bo* next_bo;
+ GBM.gbm_bo* next_bo;
uint fb;
-// fds = new PollFD();
-// fds.fd = fd_gpu;
-// fds.events = PollFlags.In;
-
-// evctx = new EventContext();
-// evctx.version = EventContext.Version;
-// evctx.page_flip_handler = PageFlipPtr;
int timeout = -1;//block ? -1 : 0;
Console.WriteLine ("addFb failed: {0}", ret);
next_bo->SetUserData (ref fb, handleDestroyFB);
- if (bo == null) {
+ if (bo == null) {
uint connId = connector.Id;
ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
if (ret != 0)
while (is_flip_queued != 0) {
fds.revents = 0;
if (Libc.poll (ref fds, 1, timeout) < 0)
- break;
+ break;
if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
break;
if ((fds.revents & PollFlags.In) != 0)
}
boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888,
GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write);
-
+
// Copy cursor.Data into a new buffer of the correct size
byte[] cursor_data = new byte[width * height * 4];
for (uint y = 0; y < cursor.Height; y++)
mode.flags |= (uint)VideoMode.PVSYNC;
return mode;
}
- unsafe void setScanOutRegion(){
-
- //currentCrtc.handle->mode = currentMode;
- // ModeInfo* mode = (ModeInfo*)Marshal.AllocHGlobal (sizeof(ModeInfo));// pConnector->modes;
- // *mode = currentMode;
-
- uint fb;
- GBM.gbm_bo* bo = GBM.BufferObject.gbm_bo_create (gbmDev.handle, (uint)Width, (uint)Height, GBM.SurfaceFormat.ARGB8888, GBM.SurfaceFlags.Rendering);
- int ret = drmModeAddFB (fd_gpu, (uint)Width, (uint)Height, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
- if (ret != 0)
- Console.WriteLine ("addFb failed: {0}", ret);
- bo->SetUserData (ref fb, handleDestroyFB);
-
- uint connId = connector.Id;
- ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, currentCrtc.CurrentFbId, 0, 0, &connId, 1, ref currentMode);
- if (ret != 0)
- Console.WriteLine ("set new mode setCrtc failed: {0}", ret);
- //GBM.BufferObject.gbm_bo_destroy (bo);
- Console.WriteLine ("new mode set to {0} x {1} fbid:{2}", Width, Height, currentCrtc.CurrentFbId);
- }
// unsafe public drmPlane GetPlane (uint id) {
// drmPlane p = new drmPlane();
// p.x, p.y,
// src_w, src_h);
//
-//
+//
// }
#region IDisposable implementation
Dispose (true);
GC.SuppressFinalize (this);
}
+ bool disposed = false;
protected virtual void Dispose (bool disposing){
+ if (disposed)
+ return;
unsafe{
if (bo != null)
- gbmSurf.Release (bo);
+ gbmSurf.Release (bo);
}
- Thread.Sleep (10);
+ if (fb != 0)
+ if (drmModeRmFB (fd_gpu, fb) != 0)
+ Console.WriteLine ("DestroyFB failed");
+ if (eglctx != null)
+ eglctx.ResetMakeCurrent ();
if (cairoDev != null) {
cairoDev.Release ();
CairoSurf.Dispose ();
}
if (eglctx != null) {
eglctx.ResetMakeCurrent ();
- eglctx.DestroyContext ();
-
if (eglSurf != null)
- eglSurf.Dispose ();
+ eglSurf.Dispose ();
eglSurf = null;
+ if (eglctx != null)
+ eglctx.Dispose ();
+ eglctx = null;
}
if (gbmSurf != null)
gbmSurf.Dispose ();
- if (eglctx != null)
- eglctx.Dispose ();
- eglctx = null;
if (gbmDev != null)
gbmDev.Dispose ();
-
if (currentCrtc != null)
- currentCrtc.Dispose ();
+ currentCrtc.Dispose ();
if (connector != null)
- connector.Dispose ();
+ connector.Dispose ();
if (resources != null)
resources.Dispose ();
resources = null;
if (fd_gpu > 0)
Libc.close (fd_gpu);
fd_gpu = -1;
+ disposed = true;
Console.WriteLine ("GPU controler disposed");
}
#endregion
-
-
- unsafe public void MarkFBDirty(){
- IntPtr pClip = Marshal.AllocHGlobal (sizeof(drmClip));
- drmClip dc = new drmClip () { x1 = 0, y1 = 0, x2 = 500, y2 = 500 };
- Marshal.StructureToPtr (dc, pClip,false);
- int ret = drmModeDirtyFB (fd_gpu, currentCrtc.CurrentFbId, IntPtr.Zero, 0);
- if (ret < 0)
- Console.WriteLine ("set FB dirty failed: {0}", ret);
- }
-
-
-// unsafe static bool paint(gbm_bo * bo)
-// {
-// uint w = (uint)bo->Width;
-// uint h = (uint)bo->Height;
-// uint stride = (uint)bo->Stride;
-//
-// Console.WriteLine ("trying to map bo: {0}x{1} stride:{2}", w, h, stride);
-// bool success = false;
-// try {
-// unsafe {
-// IntPtr map_data = IntPtr.Zero;
-// IntPtr addr = Gbm.Map (bo, 0, 0, w, h, TransferFlags.Write, ref stride, out map_data);
-// if (addr == IntPtr.Zero || map_data == IntPtr.Zero) {
-// Console.WriteLine ("failed to mmap gbm bo");
-// return false;
-// }
-// Console.WriteLine ("addr = {0}", addr.ToString());
-// byte* b = (byte*)addr;
-// for (int y = 0; y < h; y++) {
-// for (int x = 0; x < w; x++) {
-// *(b + x + y * stride) = 0xff;
-// }
-// }
-// Gbm.Unmap (bo, map_data);
-// success = true;
-// }
-// } catch (Exception ex) {
-// Console.WriteLine (ex.ToString ());
-// }
-// return success;
-// }
}
}
\ No newline at end of file
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
+using System.Collections.Generic;
namespace Linux.VT {
public enum KDMode : byte {
TEXT0 = 0x02, /* obsolete */
TEXT1 = 0x03 /* obsolete */
}
- public enum SwitchMode : sbyte {
+ public enum SwitchMode : byte {
AUTO = 0x00, /* auto vt switching */
PROCESS = 0x01, /* process controls switching */
ACKACQ = 0x02 /* acknowledge switch */
UNICODE = 0x03,
OFF = 0x04,
}
+ [StructLayout(LayoutKind.Sequential)]
public struct vt_mode {
public SwitchMode mode; /* vt mode */
- public sbyte waitv; /* if set, hang on writes if not active */
+ public byte waitv; /* if set, hang on writes if not active */
public short relsig; /* signal to raise on release req */
public short acqsig; /* signal to raise on acquisition */
public short frsig; /* unused (set to 0) */
+ public override string ToString ()
+ {
+ return string.Format ("[vt_mode]:waitv:{0} relsig:{1} acqsig:{2} switchmode:{3}", waitv, relsig, acqsig, mode);
+ }
}
public struct State {
public ushort v_active; /* active vt */
public ushort v_cols; /* number of columns */
public ushort v_scrollsize; /* number of lines of scrollback */
}
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe public struct KbsEntry {
+ public byte kb_func;
+ fixed byte kb_string[512];
+
+ public string KbString {
+ get {
+ fixed(byte* bytes = kb_string) {
+ int i = 0;
+ List<byte> lb = new List<byte> ();
+ while (i<512){
+ byte b = (byte)*(bytes + i);
+ if ((int)b == 0)
+ break;
+ lb.Add (b);
+ i++;
+ }
+ string test = System.Text.Encoding.ASCII.GetString (lb.ToArray ());
+
+ return test;
+ }
+
+ }
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
public struct KbEntry {
- public byte kb_table;
+ public KbTable kb_table;
public byte kb_index;
public ushort kb_value;
+
+ public byte ActionCode { get { return (byte)(kb_value & 0xff);}}
+ public KtType KeyType { get { return (KtType)(kb_value>>8); }}
+
+ public override string ToString ()
+ {
+ return string.Format ("KbEntry: {0} {1} {2}", kb_table, kb_index, kb_value);
+ }
+ }
+ [Flags]public enum KtType : byte {
+ Latin = 0x00, /* we depend on this being zero */
+ Fn = 0x01,
+ Spec = 0x02,
+ Pad = 0x03,
+ Dead = 0x04,
+ Cons = 0x05,
+ Cur = 0x06,
+ Shift = 0x07,
+ Meta = 0x08,
+ Ascii = 0x09,
+ Lock = 0x0a,
+ Letter = 0x0b, /* symbol that can be acted upon by CapsLock */
+ Slock = 0x0c,
+ Dead2 = 0x0d,
+ Brl = 0x0e
}
+ [Flags]public enum KbTable : byte {
+ Normal = 0x00,
+ Shift = 0x01,
+ Alt = 0x02,
+ AltShift= 0x03
+ }
public class VTControler : IDisposable {
public int fd = -1;
#endregion
/// <summary>set Graphic or Text mode for VT. </summary>
- unsafe public KDMode KDMode {
+ public KDMode KDMode {
get {
KDMode m = 0;
if (ioctl (fd, KDGETMODE, ref m) < 0)
}
}
/// <summary>set AUTO or PROCESS mode for VT. </summary>
- unsafe public vt_mode VTMode {
+ public vt_mode VTMode {
get {
vt_mode m = new vt_mode();
if (ioctl (fd, VT_GETMODE, ref m) < 0)
throw new Exception ("VTControler: failed to set VTMode for current VT");
}
}
-
+ /// <summary>get/set keyboard mode. </summary>
+ public KbdMode KbdMode {
+ get {
+ KbdMode m = 0;
+ if (ioctl (fd, KDGKBMODE, ref m) < 0)
+ throw new Exception ("VTControler: failed to get current keyboard mode");
+ return m;
+ }
+ set {
+ if (ioctl (fd, KDSKBMODE, (int)value) < 0)
+ throw new Exception ("VTControler: failed to set current keyboard mode");
+ }
+ }
/// <summary>
/// Switchs to V.
/// </summary>
if (ioctl (fd, VT_RELDISP, ACKACQ)<0)
throw new Exception ("VTControler: failed to acknowledge switch with VT_RELDISP");
}
+ public void AtachProcessTOTTY (int ttyNum){
+ int ret =ioctl (fd, TIOCSCTTY, ttyNum);
+ if (ret<0)
+ throw new Exception (string.Format ("VTControler: failed to attach process to TTY {0}: {1}",ttyNum,ret));
+ }
+ public void DetachProcess () {
+ if (ioctl (fd, TIOCNOTTY, 0)<0)
+ throw new Exception ("VTControler: failed to dettach process from TTY");
+ }
+
+ public KbEntry GetKDBEntry (KbTable table, byte index){
+ KbEntry ke = new KbEntry() { kb_table = table, kb_index = index};
+ int ret = ioctl (fd, KDGKBENT, ref ke);
+ if (ret < 0)
+ throw new Exception ("VTControler: failed to get KDEntry: " + ret );
+ return ke;
+ }
+ public string GetKbString (byte action_code){
+ KbsEntry ke = new KbsEntry() { kb_func = action_code};
+ int ret = ioctl (fd, KDGKBSENT, ref ke);
+ if (ret < 0)
+ throw new Exception ("VTControler: failed to get KDSEntry: " + ret );
+ return ke.KbString;
+ }
#region IDisposable implementation
~VTControler(){
const uint KDSKBMODE = 0x4B45; /* sets current keyboard mode */
const uint KDGKBENT = 0x4B46; /* gets one entry in translation table */
const uint KDSKBENT = 0x4B47; /* sets one entry in translation table */
+ const uint KDGKBSENT = 0x4B48; /* gets one function key string entry */
+ const uint KDSKBSENT = 0x4B49; /* sets one function key string entry */
const uint VT_OPENQRY = 0x5600; /* find available vt */
const uint VT_GETMODE = 0x5601; /* get mode of active vt */
const uint VT_DISALLOCATE= 0x5608; /* free memory associated to vt */
const uint VT_RESIZE = 0x5609; /* set kernel's idea of screensize */
+ const uint TIOCNOTTY = 0x5422; /* dettach process from tty */
+ const uint TIOCSCTTY = 0x540E; /* attach process to tty */
#endregion
#region ioctl overrides
[DllImport("libc")]
static extern int ioctl(int d, uint request, ref KbEntry entry);
[DllImport("libc")]
+ static extern int ioctl(int d, uint request, ref KbsEntry entry);
+ [DllImport("libc")]
static extern int ioctl(int d, uint request, ref KbdMode value);
[DllImport("libc")]
static extern int ioctl(int d, uint request, ref long value);
FpsLabel {
Width = 50%;
- Font = droid, 10;
+ Font = droid, 8;
Margin = 0;
TextAlignment = Center;
Background = Onyx;
}
FpsDisp {
- Font = droid bold, 10;
+ Font = droid , 8;
Width = 50%;
Margin = 0;
TextAlignment = Center;
Background = Teal;
}
-CheckBox2 {
- Template= #Tests.Interfaces.CheckBox2.imlt;
- Background = Onyx;
- Checked={Background=Mantis;Font=droid bold, 10};
- Unchecked = {Background=Onyx;Font=droid,10};
-}
-RadioButton2 {
- Template=#Tests.Interfaces.CheckBox2.imlt;
- Background = Onyx;
- Checked = {Background=Mantis;Font=droid bold, 10};
- Unchecked = {Background=Onyx;Font=droid,10};
-}
-labPerf {
- Font = droid, 8;
- Width = 50%;
-}
-labPerfVal{
- Font = droid, 8;
- Width = 50%;
+Window {
+ Template = #Crow.ToolWindow.template;
}
<IntermediateOutputPath>$(SolutionDir)build/obj/$(Configuration)</IntermediateOutputPath>
<CustomCommands>
<CustomCommands>
+ <Command type="BeforeExecute" command="sudo setcap CAP_SYS_ADMIN=+ep ${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" />
<Command type="Execute" command="${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" />
</CustomCommands>
</CustomCommands>
- <StartupObject>testDrm.TestApp</StartupObject>
+ <StartupObject>testDrm.Tests</StartupObject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
<OutputPath>$(SolutionDir)build\Debug</OutputPath>
- <Externalconsole>true</Externalconsole>
+ <CustomCommands>
+ <CustomCommands>
+ <Command type="BeforeExecute" command="sudo setcap CAP_SYS_ADMIN=+ep ${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" />
+ <Command type="Execute" command="${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" pauseExternalConsole="True" />
+ </CustomCommands>
+ </CustomCommands>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="src\Linux\Bindings\Drm.cs" />
- <Compile Include="src\Linux\Bindings\Evdev.cs" />
<Compile Include="src\Linux\Bindings\Gbm.cs" />
<Compile Include="src\Linux\Bindings\Kms.cs" />
<Compile Include="src\Linux\Bindings\Libc.cs" />
<Compile Include="Main.cs" />
<Compile Include="src\Linux\DRI\PlaneResources.cs" />
<Compile Include="src\Linux\DRI\DRIControler.cs" />
+ <Compile Include="tests.cs" />
+ <Compile Include="testLibInput.cs" />
+ <Compile Include="src\EVDEV\Device.cs" />
+ <Compile Include="src\Linux\Bindings\EvdevClass.cs" />
+ <Compile Include="defineToEnum.cs" />
+ <Compile Include="src\EVDEV\Enums.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
+ <Reference Include="Mono.Posix" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\" />
<Folder Include="src\Linux\DRI\" />
<Folder Include="src\Egl\" />
<Folder Include="src\Linux\GBM\" />
+ <Folder Include="src\EVDEV\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Crow.csproj">
</ItemGroup>
<ItemGroup>
<None Include="src\DRMContext.cs" />
- <None Include="tests.cs" />
</ItemGroup>
</Project>
\ No newline at end of file
--- /dev/null
+//
+// testLibInput.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.Diagnostics;
+using Linux;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Crow;
+using OpenTK.Platform.Linux;
+using System.IO;
+
+namespace testDrm
+{
+ public class testLibInput
+ {
+ static void Main(){
+
+ testLibInput tli = new testLibInput();
+ tli.run ();
+ }
+ public testLibInput ()
+ {
+ Console.WriteLine ("starting");
+ initInput ();
+ }
+ void run(){
+ while (true)
+ Console.ReadKey (true);
+ }
+ #region INPUT
+ Thread input_thread;
+ long exit;
+
+ static readonly object Sync = new object();
+ static readonly Crow.Key[] KeyMap = Linux.oldEvDev.EvdevClass.KeyMap;
+ static long DeviceFDCount;
+
+ IntPtr udev;
+ IntPtr input_context;
+
+ int input_fd = 0;
+
+ InputInterface input_interface = new InputInterface(
+ OpenRestricted, CloseRestricted);
+ static CloseRestrictedCallback CloseRestricted = CloseRestrictedHandler;
+ static void CloseRestrictedHandler(int fd, IntPtr data)
+ {
+ Debug.Print("[Input] Closing fd {0}", fd);
+ int ret = Libc.close(fd);
+
+ if (ret < 0)
+ {
+ Debug.Print("[Input] Failed to close fd {0}. Error: {1}", fd, ret);
+ }
+ else
+ {
+ Interlocked.Decrement(ref DeviceFDCount);
+ }
+ }
+
+ static OpenRestrictedCallback OpenRestricted = OpenRestrictedHandler;
+ static int OpenRestrictedHandler(IntPtr path, int flags, IntPtr data)
+ {
+ int fd = Libc.open(path, (OpenFlags)flags);
+ Debug.Print("[Input] Opening '{0}' with flags {1}. fd:{2}",
+ Marshal.PtrToStringAnsi(path), (OpenFlags)flags, fd);
+
+ if (fd >= 0)
+ {
+ Interlocked.Increment(ref DeviceFDCount);
+ }
+
+ return fd;
+ }
+
+ void initInput (){
+ Semaphore ready = new Semaphore(0, 1);
+ input_thread = new Thread (InputThreadLoop);
+ input_thread.Name = "input_thread";
+ input_thread.IsBackground = true;
+ input_thread.Start(ready);
+ }
+
+ void InputThreadLoop(object semaphore)
+ {
+ Debug.Print("[Input] Running on thread {0}", Thread.CurrentThread.ManagedThreadId);
+ Setup();
+
+ // Inform the parent thread that initialization has completed successfully
+ (semaphore as Semaphore).Release();
+ Debug.Print("[Input] Released main thread.", input_context);
+
+ // Use a blocking poll for input messages, in order to reduce CPU usage
+ PollFD poll_fd = new PollFD();
+ poll_fd.fd = input_fd;
+ poll_fd.events = PollFlags.In;
+ Debug.Print("[Input] Created PollFD({0}, {1})", poll_fd.fd, poll_fd.events);
+
+ Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events);
+ while (Interlocked.Read(ref exit) == 0)
+ {
+
+ //drmTimeOut.Restart ();
+
+ int ret = Libc.poll(ref poll_fd, 1, -1);
+ ErrorNumber error = (ErrorNumber)Marshal.GetLastWin32Error();
+ bool is_error =
+ ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
+ (poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
+
+ if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
+ ProcessEvents(input_context);
+
+ if (is_error)
+ {
+ Debug.Print("[Input] Exiting input loop {0} due to poll error [ret:{1} events:{2}]. Error: {3}.",
+ input_thread.ManagedThreadId, ret, poll_fd.revents, error);
+ Interlocked.Increment(ref exit);
+ }
+ }
+ Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
+ }
+
+ void Setup()
+ {
+ // Todo: add static path fallback when udev is not installed.
+ udev = Udev.New();
+ if (udev == IntPtr.Zero)
+ {
+ Debug.Print("[Input] Udev.New() failed.");
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] Udev.New() = {0:x}", udev);
+
+ input_context = LibInput.CreateContext(input_interface, IntPtr.Zero, udev);
+ if (input_context == IntPtr.Zero)
+ {
+ Debug.Print("[Input] LibInput.CreateContext({0:x}) failed.", udev);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.CreateContext({0:x}) = {1:x}", udev, input_context);
+
+ string seat_id = "seat0";
+ int seat_assignment = LibInput.AssignSeat(input_context, seat_id);
+ if (seat_assignment == -1)
+ {
+ Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1} failed.", input_context, seat_id);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1}", input_context, seat_id);
+
+ input_fd = LibInput.GetFD(input_context);
+ if (input_fd < 0)
+ {
+ Debug.Print("[Input] LibInput.GetFD({0:x}) failed.", input_context);
+ Interlocked.Increment(ref exit);
+ return;
+ }
+ Debug.Print("[Input] LibInput.GetFD({0:x}) = {1}.", input_context, input_fd);
+
+ ProcessEvents(input_context);
+ LibInput.Resume(input_context);
+ Debug.Print("[Input] LibInput.Resume({0:x})", input_context);
+
+ if (Interlocked.Read(ref DeviceFDCount) <= 0)
+ {
+ Debug.Print("[Error] Failed to open any input devices.");
+ Debug.Print("[Error] Ensure that you have access to '/dev/input/event*'.");
+ Interlocked.Increment(ref exit);
+ }
+ }
+
+ void ProcessEvents(IntPtr input_context)
+ {
+ // Process all events in the event queue
+ while (true)
+ {
+ // Data available
+ int ret = LibInput.Dispatch(input_context);
+ if (ret != 0)
+ {
+ Debug.Print("[Input] LibInput.Dispatch({0:x}) failed. Error: {1}",
+ input_context, ret);
+ break;
+ }
+
+ IntPtr pevent = LibInput.GetEvent(input_context);
+ if (pevent == IntPtr.Zero)
+ {
+ break;
+ }
+
+ IntPtr device = LibInput.GetDevice(pevent);
+ InputEventType type = LibInput.GetEventType(pevent);
+
+ lock (Sync)
+ {
+ switch (type)
+ {
+ // case InputEventType.DeviceAdded:
+ // HandleDeviceAdded(input_context, device);
+ // break;
+ //
+ // case InputEventType.DeviceRemoved:
+ // HandleDeviceRemoved(input_context, device);
+ // break;
+ //
+ case InputEventType.KeyboardKey:
+ //run = false;
+ handleKeyboard(LibInput.GetKeyboardEvent(pevent));
+ break;
+ //
+
+
+ // case InputEventType.PointerMotionAbsolute:
+ // handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent));
+ // break;
+ }
+ }
+
+ LibInput.DestroyEvent(pevent);
+ }
+ }
+
+
+
+ KeyModifiers curModifiers = KeyModifiers.None;
+
+ void handleKeyboard(KeyboardEvent e)
+ {
+ int key = (int)Linux.oldEvDev.EvdevClass.KeyMap [e.Key];
+ Key k = (Key)key;
+ if (e.KeyState == KeyState.Pressed) {
+ Console.WriteLine ("KeyDown: raw:{0} evdev:{1} key:{2}",e.Key, key,k);
+ switch (k) {
+ case Key.ShiftLeft:
+ case Key.ShiftRight:
+ curModifiers |= KeyModifiers.Shift;
+ break;
+ case Key.ControlLeft:
+ case Key.ControlRight:
+ curModifiers |= KeyModifiers.Control;
+ break;
+ case Key.AltLeft:
+ curModifiers |= KeyModifiers.Alt;
+ break;
+ case Key.AltRight:
+ curModifiers |= KeyModifiers.AltGr;
+ break;
+ }
+ }else {
+ Console.WriteLine ("KeyUp: raw:{0} evdev:{1} key:{2}",e.Key, key,k);
+ switch (k) {
+ case Key.ShiftLeft:
+ case Key.ShiftRight:
+ curModifiers &= ~KeyModifiers.Shift;
+ break;
+ case Key.ControlLeft:
+ case Key.ControlRight:
+ curModifiers &= ~KeyModifiers.Control;
+ break;
+ case Key.AltLeft:
+ curModifiers &= ~KeyModifiers.Alt;
+ break;
+ case Key.AltRight:
+ curModifiers &= ~KeyModifiers.AltGr;
+ break;
+ }
+ // if (!keymap.ContainsKey (curModifiers)) {
+ // Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers);
+ // return;
+ // }
+ // string tmp = keymap [curModifiers] [e.Key];
+ // if (string.IsNullOrEmpty (tmp))
+ // return;
+ // if (char.IsControl (tmp[0]))
+ // return;
+ // CrowInterface.ProcessKeyPress (tmp [0]);
+ }
+ }
+
+ #endregion
+
+ }
+}
+
using Crow;
using System.Diagnostics;
-
+using Linux.Evdev;
+using Linux.VT;
namespace testDrm
{
- public class TestApp : Application, IValueChange
+ static class Tests
{
- #region IValueChange implementation
- public event EventHandler<ValueChangeEventArgs> ValueChanged;
- public virtual void NotifyValueChanged(string MemberName, object _value)
+ static void Main ()
{
- //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
- ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value));
- }
- #endregion
-
- public bool Running = true;
-
- public TestApp () : base () {
-
+// using (VTControler vt = new VTControler()){
+// Console.WriteLine (vt.CurrentVT);
+//
+// for (byte i = 0; i < 0x7F; i++) {
+// Console.Write ("{0:X2}: ", i);
+// printke (vt.GetKDBEntry (KbTable.Normal, i));
+// printke (vt.GetKDBEntry (KbTable.Shift, i));
+// printke (vt.GetKDBEntry (KbTable.Alt, i));
+// Console.Write ("\n");
+// }
+// }
+// //return;
+ testEVDEV ();
}
- int frTime = 0;
- int frMin = int.MaxValue;
- int frMax = 0;
-
- public override void Run ()
- {
- Stopwatch frame = new Stopwatch ();
- Load ("#testDrm.ui.menu.crow").DataSource = this;
- Load ("#testDrm.ui.0.crow").DataSource = this;
-
- while(Running){
- try {
- frame.Restart();
- base.Run ();
- frame.Stop();
- frTime = (int)frame.ElapsedTicks;
- NotifyValueChanged("frameTime", frTime);
- if (frTime > frMax){
- frMax = frTime;
- NotifyValueChanged("frameMax", frMax);
- }
- if (frTime < frMin){
- frMin = frTime;
- NotifyValueChanged("frameMin", frMin);
+// static void printke(KbEntry ke){
+// string output = "";
+// if (ke.KeyType.HasFlag (KtType.Latin))
+// output = new string(new char[] {ke.ActionCode});
+// if (ke.KeyType.HasFlag (KtType.Fn))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Spec))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Pad))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Dead))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Cons))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Cur))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Shift))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Meta))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Ascii))
+// output = new string(new char[] {ke.ActionCode});
+// if (ke.KeyType.HasFlag (KtType.Lock))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Letter))
+// output = new string(new char[] {ke.ActionCode});
+// if (ke.KeyType.HasFlag (KtType.Slock))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Dead2))
+// break;
+// if (ke.KeyType.HasFlag (KtType.Brl))
+// break;
+//
+//// if (!ke.KeyType.HasFlag(KtType.)|ke.KeyType.HasFlag(KtType.Letter))
+//// Console.Write ("{0:X4} '{1}' ", ke.kb_value, (char)ke.ActionCode);
+// }
+ static void evThread (){
+ using (VTControler vt = new VTControler ()) {
+ using (Device dev = new Device (0)) {
+ Console.WriteLine (dev.Name);
+ Console.WriteLine ("Physical location: {0}", dev.PhysLocation);
+ Console.WriteLine ("\tbus:{0}\n\tvendor:{1}\n\tproduct:{2}\n\tversion:{3}",
+ dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId);
+
+ while (true) {
+ InputEvent evt;
+ if (!dev.GetNextEvent (out evt))
+ continue;
+
}
-
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString());
}
}
}
- void onQuitClick(object send, Crow.MouseButtonEventArgs e)
- {
- Running = false;
+ static void dumpDevices (){
+ string[] devices = Directory.GetFiles("/dev/input", "event*");
+ foreach (string path in devices) {
+ using (Device dev = new Device (path)) {
+ Console.Write (dev.Name + " => ");
+ Console.WriteLine ("\tbus:{0} vendor:{1} product:{2} version:{3} path:{4}",
+ dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId, path);
+ if (dev.HasEventCodeOfType (EvType.Key, (uint)Linux.Evdev.KeyType.A))
+ Console.WriteLine ("\t\thas a key");
+ }
+ }
}
- }
- static class Tests
- {
+
+ static void testEVDEV (){
+
+ using (Device dev = new Device (0)) {
+ Console.WriteLine (dev.Name);
+ Console.WriteLine ("Physical location: {0}", dev.PhysLocation);
+ Console.WriteLine ("\tbus:{0}\n\tvendor:{1}\n\tproduct:{2}\n\tversion:{3}",
+ dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId);
+ dev.test2 ();
+//
+// if (!dev.TryGrab ()) {
+// Console.WriteLine ("failed to grab device");
+// return;
+// }
+// using (VTControler vt = new VTControler ()) {
+// while (true) {
+// InputEvent evt;
+// if (!dev.GetNextEvent (out evt))
+// continue;
+// if (evt.Code == (ushort)Linux.Evdev.KeyType.Esc && evt.Value == 1)
+// break;
+// if (evt.Type != EvType.Key)
+// continue;
+// KbEntry ke = vt.GetKDBEntry (KbTable.Normal, (byte)evt.Code);
+// Console.WriteLine (evt.ToString ());
+// Console.WriteLine ("raw={0} {1} {2}", evt.Code, ke.KeyType, (char)ke.ActionCode);
+// }
+// }
+// dev.TryRelease ();
+ }
+
+//
+// Thread t = new Thread(evThread);
+// t.IsBackground = true;
+// t.Start ();
+//
+// while (true)
+// Console.ReadKey (true);
+ }
+
static void signal_handler (Signal s){
Console.WriteLine ("signal catched: " + s.ToString());
}
+ static void switch_request_handle (Signal s){
+ Console.WriteLine ("switch signal catched: " + s.ToString());
+ }
static void genEglConstCase (){
Dictionary<int,string> dic = new Dictionary<int, string> ();
}
}
}
- static void Main ()
- {
- try {
- using (TestApp crowApp = new TestApp ()) {
- crowApp.Run ();
- }
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString ());
- }
- }
static void testApp () {
int previousVT = -1, appVT = -1;
}
}
- static void testKMS(){
- int previousVT = -1, appVT = -1;
-
- if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0)
- throw new Exception ("signal handler registation failed");
- if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0)
- throw new Exception ("SIGINT handler registation failed");
-
- using (VT.VTControler master = new VT.VTControler ()) {
- previousVT = master.CurrentVT;
- appVT = master.FirstAvailableVT;
- master.SwitchTo (appVT);
- try {
- master.KDMode = VT.KDMode.GRAPHICS;
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString ());
- }
- }
- try {
- using (DRI.GPUControler gpu = new DRI.GPUControler ()) {
-
-// int i = 0;
-// while(running && i < 1000){
-// try {
-// gpu.Update ();
-// i++;
-// } catch (Exception ex) {
-// Console.WriteLine (ex.ToString());
-// }
-//
-// }
-
-
- }
- } catch (Exception ex) {
- Console.WriteLine (ex.ToString ());
- }
- using (VT.VTControler master = new VT.VTControler ()) {
- // try {
- // master.KDMode = VT.KDMode.TEXT;
- // } catch (Exception ex) {
- // Console.WriteLine (ex.ToString ());
- // }
- master.SwitchTo (previousVT);
- }
- }
static void signalTest (){
if (Kernel.signal (Signal.SIGINT, signal_handler) < 0)
throw new Exception ("signal handler registation failed");
+ if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0)
+ throw new Exception ("signal handler registation failed");
Console.WriteLine ("Handler registered for {0}", Signal.SIGINT);
while (true)
Thread.Sleep (1);
//vtc.CurrentMode = VT.Mode.GRAPHICS;
}
static bool running = true;
- static void switch_request_handle (Signal s){
- Console.WriteLine ("switch request catched: " + s.ToString());
- using (VT.VTControler master = new VT.VTControler ()) {
- Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
- master.AcknoledgeSwitchRequest ();
- }
- }
+// static void switch_request_handle (Signal s){
+// Console.WriteLine ("switch request catched: " + s.ToString());
+// using (VT.VTControler master = new VT.VTControler ()) {
+// Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
+// master.AcknoledgeSwitchRequest ();
+// }
+// }
static void sigint_handler (Signal s){
Console.WriteLine ("SIGINT catched");
running = false;
<?xml version="1.0"?>
<Menu>
<MenuItem Caption="File" Width="Fit">
- <MenuItem Caption="New" MouseClick="onLoadClick"/>
- <MenuItem Caption="Open"/>
+ <MenuItem Caption="New"/>
+ <MenuItem Command="{CMDOpen}"/>
<MenuItem Caption="Save"/>
<MenuItem Caption="Quit" MouseClick="onQuitClick"/>
</MenuItem>
<?xml version="1.0"?>
-<Window Focusable="true" Caption="Measures" Width="30%" Height="Fit" MinimumSize="100,100">
- <ListBox Data="{PerfMeasures}" Fit="true"
- ItemTemplate="#ui.perfMsr.crow"/>
+<Window Focusable="true" Caption="Measures" Width="200" Height="360" MinimumSize="100,100" Background="0.2,0.2,0.2,0.2" CornerRadius="10">
+ <ListBox Data="{PerfMeasures}" Fit="true" ItemTemplate="#ui.perfMsr.crow" Background="Transparent"/>
</Window>
<?xml version="1.0"?>
-
<VerticalStack Spacing="0" Fit="true" Width="160">
<HorizontalStack Background="Black">
- <Label Text="{Name}" Width="Stretched" Font="doid bold, 10" Margin="2"/>
- <Button Caption="Reset" MouseClick="onResetClick" Height="Fit"/>
+ <Label Text="{Name}" Width="Stretched" Font="doid bold, 10" Margin="1"/>
+ <Button Caption="RAZ" MouseClick="onResetClick" Height="Fit"/>
</HorizontalStack>
<HorizontalStack>
<Label Text="Current:" Style="FpsLabel"/>