From 97b211a101ca4ea4da090a54b2e68152012dfb66 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Sun, 18 May 2014 22:04:52 +0200 Subject: [PATCH 1/3] [EGL] Egl.GetProcAddress only returns extensions We have to load statically exported entry points using the regular OS symbol loading facilities, and only use eglGetProcAddress for extensions. Fixes crash in https://github.com/mono/MonoGame/pull/2377 --- Source/OpenTK/OpenTK.csproj | 7 +- Source/OpenTK/Platform/Egl/EglContext.cs | 27 +++++- Source/OpenTK/Platform/Egl/EglUnixContext.cs | 79 ++++++++++++++++++ Source/OpenTK/Platform/Egl/EglWinContext.cs | 83 +++++++++++++++++++ .../Platform/Egl/EglWinPlatformFactory.cs | 4 +- .../Platform/Egl/EglX11PlatformFactory.cs | 4 +- Source/OpenTK/Platform/X11/Bindings/DL.cs | 58 +++++++++++++ 7 files changed, 251 insertions(+), 11 deletions(-) create mode 100644 Source/OpenTK/Platform/Egl/EglUnixContext.cs create mode 100644 Source/OpenTK/Platform/Egl/EglWinContext.cs create mode 100644 Source/OpenTK/Platform/X11/Bindings/DL.cs diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 502877fb..5ce24dfc 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -163,9 +163,12 @@ + + + @@ -828,7 +831,5 @@ - - - + \ No newline at end of file diff --git a/Source/OpenTK/Platform/Egl/EglContext.cs b/Source/OpenTK/Platform/Egl/EglContext.cs index d0aa48b6..6cbb1e58 100644 --- a/Source/OpenTK/Platform/Egl/EglContext.cs +++ b/Source/OpenTK/Platform/Egl/EglContext.cs @@ -31,10 +31,12 @@ using OpenTK.Graphics; namespace OpenTK.Platform.Egl { - class EglContext : EmbeddedGraphicsContext + abstract class EglContext : EmbeddedGraphicsContext { #region Fields + readonly RenderableFlags Renderable; + EglWindowInfo WindowInfo; IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } } int swap_interval = 1; // Default interval is defined as 1 in EGL. @@ -62,10 +64,11 @@ namespace OpenTK.Platform.Egl // Select an EGLConfig that matches the desired mode. We cannot use the 'mode' // parameter directly, since it may have originated on a different system (e.g. GLX) // and it may not support the desired renderer. + Renderable = major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES; Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, mode.Buffers, mode.Stereo, - major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES); + Renderable); if (!Mode.Index.HasValue) throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); IntPtr config = Mode.Index.Value; @@ -144,11 +147,27 @@ namespace OpenTK.Platform.Egl public override IntPtr GetAddress(IntPtr function) { - return Egl.GetProcAddress(function); + // Try loading a static export from ES1 or ES2 + IntPtr address = GetStaticAddress(function, Renderable); + + // If a static export is not available, try retrieving an extension + // function pointer with eglGetProcAddress + if (address == IntPtr.Zero) + { + address = Egl.GetProcAddress(function); + } + + return address; } #endregion + #region Abstract Members + + protected abstract IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable); + + #endregion + #region IDisposable Members public override void Dispose() @@ -159,7 +178,7 @@ namespace OpenTK.Platform.Egl // Todo: cross-reference the specs. What should happen if the context is destroyed from a different // thread? - void Dispose(bool manual) + protected virtual void Dispose(bool manual) { if (!IsDisposed) { diff --git a/Source/OpenTK/Platform/Egl/EglUnixContext.cs b/Source/OpenTK/Platform/Egl/EglUnixContext.cs new file mode 100644 index 00000000..5880138e --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglUnixContext.cs @@ -0,0 +1,79 @@ +#region License +// +// EglUnixContext.cs +// +// Author: +// Stefanos A. +// +// 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 OpenTK.Graphics; + +namespace OpenTK.Platform.Egl +{ + class EglUnixContext : EglContext + { + readonly IntPtr ES1 = OpenTK.Platform.X11.DL.Open("libGLESv1_CM", X11.DLOpenFlags.Lazy); + readonly IntPtr ES2 = OpenTK.Platform.X11.DL.Open("libGLESv2", X11.DLOpenFlags.Lazy); + + public EglUnixContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + : base(mode, window, sharedContext, major, minor, flags) + { + } + + public EglUnixContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + : base(handle, window, sharedContext, major, minor, flags) + { + } + + protected override IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable) + { + if ((renderable & RenderableFlags.ES) != 0 && ES1 != IntPtr.Zero) + { + return X11.DL.Symbol(ES1, function); + } + else if ((renderable & RenderableFlags.ES2) != 0 && ES2 != IntPtr.Zero) + { + return X11.DL.Symbol(ES2, function); + } + return IntPtr.Zero; + } + + protected override void Dispose(bool manual) + { + if (ES1 != IntPtr.Zero) + { + X11.DL.Close(ES1); + } + if (ES2 != IntPtr.Zero) + { + X11.DL.Close(ES2); + } + + base.Dispose(manual); + } + } +} diff --git a/Source/OpenTK/Platform/Egl/EglWinContext.cs b/Source/OpenTK/Platform/Egl/EglWinContext.cs new file mode 100644 index 00000000..9c6ee616 --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglWinContext.cs @@ -0,0 +1,83 @@ +#region License +// +// EglWinContext.cs +// +// Author: +// Stefanos A. +// +// 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 OpenTK.Graphics; + +namespace OpenTK.Platform.Egl +{ + class EglWinContext : EglContext + { + readonly IntPtr ES1 = OpenTK.Platform.Windows.Functions.LoadLibrary("libGLESv1_CM"); + readonly IntPtr ES2 = OpenTK.Platform.Windows.Functions.LoadLibrary("libGLESv2"); + + public EglWinContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + : base(mode, window, sharedContext, major, minor, flags) + { + } + + public EglWinContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + : base(handle, window, sharedContext, major, minor, flags) + { + } + + #region Protected Members + + protected override IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable) + { + if ((renderable & RenderableFlags.ES) != 0 && ES1 != IntPtr.Zero) + { + return Windows.Functions.GetProcAddress(ES1, function); + } + else if ((renderable & RenderableFlags.ES2) != 0 && ES2 != IntPtr.Zero) + { + return Windows.Functions.GetProcAddress(ES2, function); + } + return IntPtr.Zero; + } + + protected override void Dispose(bool manual) + { + if (ES1 != IntPtr.Zero) + { + Windows.Functions.FreeLibrary(ES1); + } + if (ES2 != IntPtr.Zero) + { + Windows.Functions.FreeLibrary(ES2); + } + + base.Dispose(manual); + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs b/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs index 18a352df..140c8a15 100644 --- a/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs +++ b/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs @@ -44,7 +44,7 @@ namespace OpenTK.Platform.Egl WinWindowInfo win_win = (WinWindowInfo)window; IntPtr egl_display = GetDisplay(win_win.DeviceContext); EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display); - return new EglContext(mode, egl_win, shareContext, major, minor, flags); + return new EglWinContext(mode, egl_win, shareContext, major, minor, flags); } public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) @@ -52,7 +52,7 @@ namespace OpenTK.Platform.Egl WinWindowInfo win_win = (WinWindowInfo)window; IntPtr egl_display = GetDisplay(win_win.DeviceContext); EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display); - return new EglContext(handle, egl_win, shareContext, major, minor, flags); + return new EglWinContext(handle, egl_win, shareContext, major, minor, flags); } public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() diff --git a/Source/OpenTK/Platform/Egl/EglX11PlatformFactory.cs b/Source/OpenTK/Platform/Egl/EglX11PlatformFactory.cs index f03efc78..e180fc5f 100644 --- a/Source/OpenTK/Platform/Egl/EglX11PlatformFactory.cs +++ b/Source/OpenTK/Platform/Egl/EglX11PlatformFactory.cs @@ -39,14 +39,14 @@ namespace OpenTK.Platform.Egl { X11WindowInfo x11_win = (X11WindowInfo)window; EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display)); - return new EglContext(mode, egl_win, shareContext, major, minor, flags); + return new EglUnixContext(mode, egl_win, shareContext, major, minor, flags); } public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) { X11WindowInfo x11_win = (X11WindowInfo)window; EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display)); - return new EglContext(handle, egl_win, shareContext, major, minor, flags); + return new EglUnixContext(handle, egl_win, shareContext, major, minor, flags); } public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() diff --git a/Source/OpenTK/Platform/X11/Bindings/DL.cs b/Source/OpenTK/Platform/X11/Bindings/DL.cs new file mode 100644 index 00000000..d89b5c3e --- /dev/null +++ b/Source/OpenTK/Platform/X11/Bindings/DL.cs @@ -0,0 +1,58 @@ +#region License +// +// DL.cs +// +// Author: +// Stefanos A. +// +// 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.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace OpenTK.Platform.X11 +{ + class DL + { + const string lib = "dl"; + + [DllImport(lib, EntryPoint = "dlopen")] + internal static extern IntPtr Open(string filename, DLOpenFlags flags); + + [DllImport(lib, EntryPoint = "dlclose")] + internal static extern int Close(IntPtr handle); + + [DllImport(lib, EntryPoint = "dlsym")] + internal static extern IntPtr Symbol(IntPtr handle, IntPtr name); + } + + enum DLOpenFlags + { + Lazy = 0x0001, + Now = 0x0002, + Global = 0x0100, + Local = 0x0000, + } +} From d483b01de0c461517817dc89478da5928c04475c Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 19 May 2014 08:31:38 +0200 Subject: [PATCH 2/3] [EGL] Fixed display connection We now use the display connection specified in EglWindowInfo throughout the EGL backend, instead of opening new connections in EglGraphicsMode. This fixes EGL errors in Egl.CreateWindowSurface. As part of this fix, all instances of IPlatformFactory.CreateGraphicsMode() have been removed. This API is no longer used in OpenTK 1.1 --- Source/OpenTK/Platform/Egl/Egl.cs | 2 +- Source/OpenTK/Platform/Egl/EglContext.cs | 10 +- Source/OpenTK/Platform/Egl/EglGraphicsMode.cs | 30 +- .../Platform/Egl/EglWinPlatformFactory.cs | 5 - Source/OpenTK/Platform/Egl/EglWindowInfo.cs | 21 +- Source/OpenTK/Platform/Factory.cs | 10 - Source/OpenTK/Platform/IPlatformFactory.cs | 2 - Source/OpenTK/Platform/PlatformFactoryBase.cs | 5 - Source/OpenTK/Platform/X11/X11Factory.cs | 5 - Source/OpenTK/Platform/X11/X11KeyMap.cs.orig | 727 ++++++++++++++++++ 10 files changed, 752 insertions(+), 65 deletions(-) create mode 100644 Source/OpenTK/Platform/X11/X11KeyMap.cs.orig diff --git a/Source/OpenTK/Platform/Egl/Egl.cs b/Source/OpenTK/Platform/Egl/Egl.cs index 78755356..f271f5db 100644 --- a/Source/OpenTK/Platform/Egl/Egl.cs +++ b/Source/OpenTK/Platform/Egl/Egl.cs @@ -207,7 +207,7 @@ namespace OpenTK.Platform.Egl public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value); [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateWindowSurface")] - public static extern EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, int[] attrib_list); + public static extern EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, IntPtr attrib_list); [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePbufferSurface")] public static extern EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list); diff --git a/Source/OpenTK/Platform/Egl/EglContext.cs b/Source/OpenTK/Platform/Egl/EglContext.cs index 6cbb1e58..37398f00 100644 --- a/Source/OpenTK/Platform/Egl/EglContext.cs +++ b/Source/OpenTK/Platform/Egl/EglContext.cs @@ -55,19 +55,15 @@ namespace OpenTK.Platform.Egl EglContext shared = (EglContext)sharedContext; - int dummy_major, dummy_minor; - if (!Egl.Initialize(window.Display, out dummy_major, out dummy_minor)) - throw new GraphicsContextException(String.Format("Failed to initialize EGL, error {0}.", Egl.GetError())); - WindowInfo = window; // Select an EGLConfig that matches the desired mode. We cannot use the 'mode' // parameter directly, since it may have originated on a different system (e.g. GLX) // and it may not support the desired renderer. Renderable = major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES; - Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat, - mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, - mode.Buffers, mode.Stereo, + Mode = new EglGraphicsMode().SelectGraphicsMode(window, + mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, + mode.AccumulatorFormat, mode.Buffers, mode.Stereo, Renderable); if (!Mode.Index.HasValue) throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); diff --git a/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs b/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs index 07f847e9..bc78bc82 100644 --- a/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs +++ b/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs @@ -32,31 +32,17 @@ using OpenTK.Graphics; namespace OpenTK.Platform.Egl { - class EglGraphicsMode : IGraphicsMode + class EglGraphicsMode { - #region IGraphicsMode Members - - public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, - int samples, ColorFormat accum, int buffers, bool stereo) - { - // According to the EGL specs, the ES flag should select ES 1.0 or higher, which - // makes sense as a default. EglContext.cs checks - return SelectGraphicsMode(color, depth, stencil, samples, accum, buffers, stereo, - RenderableFlags.ES); - } - - #endregion - - #region Public Members - - public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, + public GraphicsMode SelectGraphicsMode(EglWindowInfo window, + ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo, RenderableFlags renderable_flags) { IntPtr[] configs = new IntPtr[1]; int[] attribList = new int[] { - //Egl.SURFACE_TYPE, Egl.WINDOW_BIT, + Egl.SURFACE_TYPE, Egl.WINDOW_BIT, Egl.RENDERABLE_TYPE, (int)renderable_flags, Egl.RED_SIZE, color.Red, @@ -73,11 +59,7 @@ namespace OpenTK.Platform.Egl Egl.NONE, }; - // Todo: what if we don't wish to use the default display? - IntPtr display = Egl.GetDisplay(IntPtr.Zero); - int major, minor; - if (!Egl.Initialize(display, out major, out minor)) - throw new GraphicsModeException(String.Format("Failed to initialize display connection, error {0}", Egl.GetError())); + IntPtr display = window.Display; int num_configs; if (!Egl.ChooseConfig(display, attribList, configs, configs.Length, out num_configs) || num_configs == 0) @@ -101,7 +83,5 @@ namespace OpenTK.Platform.Egl return new GraphicsMode(active_config, new ColorFormat(r, g, b, a), d, s, sample_buffers > 0 ? samples : 0, 0, 2, false); } - - #endregion } } diff --git a/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs b/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs index 140c8a15..f0fd6e89 100644 --- a/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs +++ b/Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs @@ -63,11 +63,6 @@ namespace OpenTK.Platform.Egl }; } - public override IGraphicsMode CreateGraphicsMode() - { - return new EglGraphicsMode(); - } - #endregion #region Private Members diff --git a/Source/OpenTK/Platform/Egl/EglWindowInfo.cs b/Source/OpenTK/Platform/Egl/EglWindowInfo.cs index a19821bd..db9acb49 100644 --- a/Source/OpenTK/Platform/Egl/EglWindowInfo.cs +++ b/Source/OpenTK/Platform/Egl/EglWindowInfo.cs @@ -45,19 +45,30 @@ namespace OpenTK.Platform.Egl #endregion - #region Constructiors + #region Constructors public EglWindowInfo(IntPtr handle, IntPtr display) + : this(handle, display, IntPtr.Zero) { - Handle = handle; - Display = display; } public EglWindowInfo(IntPtr handle, IntPtr display, IntPtr surface) { Handle = handle; - Display = display; Surface = surface; + + if (display == IntPtr.Zero) + { + display = Egl.GetDisplay(IntPtr.Zero); + } + + Display = display; + + int dummy_major, dummy_minor; + if (!Egl.Initialize(Display, out dummy_major, out dummy_minor)) + { + throw new GraphicsContextException(String.Format("Failed to initialize EGL, error {0}.", Egl.GetError())); + } } #endregion @@ -72,7 +83,7 @@ namespace OpenTK.Platform.Egl public void CreateWindowSurface(IntPtr config) { - Surface = Egl.CreateWindowSurface(Display, config, Handle, null); + Surface = Egl.CreateWindowSurface(Display, config, Handle, IntPtr.Zero); if (Surface==IntPtr.Zero) { throw new GraphicsContextException(String.Format( diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs index 59e5d578..14185d3b 100644 --- a/Source/OpenTK/Platform/Factory.cs +++ b/Source/OpenTK/Platform/Factory.cs @@ -130,11 +130,6 @@ namespace OpenTK.Platform return default_implementation.CreateGetCurrentGraphicsContext(); } - public IGraphicsMode CreateGraphicsMode() - { - return default_implementation.CreateGraphicsMode(); - } - public IKeyboardDriver2 CreateKeyboardDriver() { return default_implementation.CreateKeyboardDriver(); @@ -195,11 +190,6 @@ namespace OpenTK.Platform throw new PlatformNotSupportedException(error_string); } - public override IGraphicsMode CreateGraphicsMode() - { - throw new PlatformNotSupportedException(error_string); - } - public override IKeyboardDriver2 CreateKeyboardDriver() { throw new PlatformNotSupportedException(error_string); diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs index c5abb9c5..f9ec7066 100644 --- a/Source/OpenTK/Platform/IPlatformFactory.cs +++ b/Source/OpenTK/Platform/IPlatformFactory.cs @@ -45,8 +45,6 @@ namespace OpenTK.Platform GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext(); - IGraphicsMode CreateGraphicsMode(); - OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver(); OpenTK.Input.IMouseDriver2 CreateMouseDriver(); diff --git a/Source/OpenTK/Platform/PlatformFactoryBase.cs b/Source/OpenTK/Platform/PlatformFactoryBase.cs index d85c645b..aa518e2c 100644 --- a/Source/OpenTK/Platform/PlatformFactoryBase.cs +++ b/Source/OpenTK/Platform/PlatformFactoryBase.cs @@ -63,11 +63,6 @@ namespace OpenTK.Platform public abstract GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext(); - public virtual IGraphicsMode CreateGraphicsMode() - { - throw new NotSupportedException(); - } - public abstract IKeyboardDriver2 CreateKeyboardDriver(); public abstract IMouseDriver2 CreateMouseDriver(); diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index af68e9fb..b3f91e4a 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -76,11 +76,6 @@ namespace OpenTK.Platform.X11 }; } - public override IGraphicsMode CreateGraphicsMode() - { - throw new NotSupportedException(); - } - public override IKeyboardDriver2 CreateKeyboardDriver() { return new X11Keyboard(); diff --git a/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig b/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig new file mode 100644 index 00000000..5846c031 --- /dev/null +++ b/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig @@ -0,0 +1,727 @@ +#region License +// +// Xkb.cs +// +// Author: +// Stefanos Apostolopoulos +// +// 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. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using OpenTK.Input; + +namespace OpenTK.Platform.X11 +{ + class X11KeyMap + { + // Keycode lookup table for current layout + readonly Key[] keycodes = new Key[256]; + readonly bool xkb_supported; + + internal X11KeyMap(IntPtr display) + { + xkb_supported = Xkb.IsSupported(display); + if (xkb_supported) + { + RefreshKeycodes(display); + } + } + + // Refreshes the keycodes lookup table based + // on the current keyboard layout. + internal void RefreshKeycodes(IntPtr display) + { + // Approach inspired by GLFW: http://www.glfw.org/ + // Huge props to the GLFW team! + if (xkb_supported) + { + unsafe + { + // Xkb.GetKeyboard appears to be broken (multiple bug reports across distros) + // so use Xkb.AllocKeyboard with Xkb.GetNames instead. + XkbDesc* keyboard = Xkb.AllocKeyboard(display); + if (keyboard != null) + { + Xkb.GetNames(display, XkbNamesMask.All, keyboard); + + for (int i = 0; i < keycodes.Length; i++) + { + keycodes[i] = Key.Unknown; + } + + // Map all alphanumeric keys of this layout + // Symbols are handled in GetKey() instead. + for (int i = keyboard->min_key_code; i <= keyboard->max_key_code; ++i) + { + string name = new string((sbyte*)keyboard->names->keys[i].name, 0, Xkb.KeyNameLength); + + Key key = Key.Unknown; + switch (name) + { + case "TLDE": + key = Key.Tilde; + break; + case "AE01": + key = Key.Number1; + break; + case "AE02": + key = Key.Number2; + break; + case "AE03": + key = Key.Number3; + break; + case "AE04": + key = Key.Number4; + break; + case "AE05": + key = Key.Number5; + break; + case "AE06": + key = Key.Number6; + break; + case "AE07": + key = Key.Number7; + break; + case "AE08": + key = Key.Number8; + break; + case "AE09": + key = Key.Number9; + break; + case "AE10": + key = Key.Number0; + break; + case "AE11": + key = Key.Minus; + break; + case "AE12": + key = Key.Plus; + break; + case "AD01": + key = Key.Q; + break; + case "AD02": + key = Key.W; + break; + case "AD03": + key = Key.E; + break; + case "AD04": + key = Key.R; + break; + case "AD05": + key = Key.T; + break; + case "AD06": + key = Key.Y; + break; + case "AD07": + key = Key.U; + break; + case "AD08": + key = Key.I; + break; + case "AD09": + key = Key.O; + break; + case "AD10": + key = Key.P; + break; + case "AD11": + key = Key.BracketLeft; + break; + case "AD12": + key = Key.BracketRight; + break; + case "AC01": + key = Key.A; + break; + case "AC02": + key = Key.S; + break; + case "AC03": + key = Key.D; + break; + case "AC04": + key = Key.F; + break; + case "AC05": + key = Key.G; + break; + case "AC06": + key = Key.H; + break; + case "AC07": + key = Key.J; + break; + case "AC08": + key = Key.K; + break; + case "AC09": + key = Key.L; + break; + case "AC10": + key = Key.Semicolon; + break; + case "AC11": + key = Key.Quote; + break; + case "AB01": + key = Key.Z; + break; + case "AB02": + key = Key.X; + break; + case "AB03": + key = Key.C; + break; + case "AB04": + key = Key.V; + break; + case "AB05": + key = Key.B; + break; + case "AB06": + key = Key.N; + break; + case "AB07": + key = Key.M; + break; + case "AB08": + key = Key.Comma; + break; + case "AB09": + key = Key.Period; + break; + case "AB10": + key = Key.Slash; + break; + case "BKSL": + key = Key.BackSlash; + break; + case "LSGT": + key = Key.Unknown; + break; + default: + key = Key.Unknown; + break; + } + + keycodes[i] = key; + } + + Xkb.FreeKeyboard(keyboard, 0, true); + } + } + } + + // Translate unknown keys (and symbols) using + // regular layout-dependent GetKey() + for (int i = 0; i < 256; i++) + { + if (keycodes[i] == Key.Unknown) + { + // TranslateKeyCode expects a XKeyEvent structure + // Make one up + XKeyEvent e = new XKeyEvent(); + e.display = display; + e.keycode = i; + Key key = Key.Unknown; + if (TranslateKeyEvent(ref e, out key)) + { + keycodes[i] = key; + } + } + } + } + + static Key TranslateXKey(XKey key) + { + switch (key) + { + case XKey.Escape: + return Key.Escape; + case XKey.Return: + return Key.Enter; + case XKey.space: + return Key.Space; + case XKey.BackSpace: + return Key.BackSpace; + + case XKey.Shift_L: + return Key.ShiftLeft; + case XKey.Shift_R: + return Key.ShiftRight; + case XKey.Alt_L: + return Key.AltLeft; + case XKey.Alt_R: + return Key.AltRight; + case XKey.Control_L: + return Key.ControlLeft; + case XKey.Control_R: + return Key.ControlRight; + case XKey.Super_L: + return Key.WinLeft; + case XKey.Super_R: + return Key.WinRight; + case XKey.Meta_L: + return Key.WinLeft; + case XKey.Meta_R: + return Key.WinRight; + case XKey.ISO_Level3_Shift: + return Key.AltRight; // Normally AltGr + + case XKey.Menu: + return Key.Menu; + case XKey.Tab: + return Key.Tab; + case XKey.minus: + return Key.Minus; + case XKey.plus: + return Key.Plus; + case XKey.equal: + return Key.Plus; + + case XKey.Caps_Lock: + return Key.CapsLock; + case XKey.Num_Lock: + return Key.NumLock; + + case XKey.F1: + return Key.F1; + case XKey.F2: + return Key.F2; + case XKey.F3: + return Key.F3; + case XKey.F4: + return Key.F4; + case XKey.F5: + return Key.F5; + case XKey.F6: + return Key.F6; + case XKey.F7: + return Key.F7; + case XKey.F8: + return Key.F8; + case XKey.F9: + return Key.F9; + case XKey.F10: + return Key.F10; + case XKey.F11: + return Key.F11; + case XKey.F12: + return Key.F12; + case XKey.F13: + return Key.F13; + case XKey.F14: + return Key.F14; + case XKey.F15: + return Key.F15; + case XKey.F16: + return Key.F16; + case XKey.F17: + return Key.F17; + case XKey.F18: + return Key.F18; + case XKey.F19: + return Key.F19; + case XKey.F20: + return Key.F20; + case XKey.F21: + return Key.F21; + case XKey.F22: + return Key.F22; + case XKey.F23: + return Key.F23; + case XKey.F24: + return Key.F24; + case XKey.F25: + return Key.F25; + case XKey.F26: + return Key.F26; + case XKey.F27: + return Key.F27; + case XKey.F28: + return Key.F28; + case XKey.F29: + return Key.F29; + case XKey.F30: + return Key.F30; + case XKey.F31: + return Key.F31; + case XKey.F32: + return Key.F32; + case XKey.F33: + return Key.F33; + case XKey.F34: + return Key.F34; + case XKey.F35: + return Key.F35; + + case XKey.a: + case XKey.A: + return Key.A; + case XKey.b: + case XKey.B: + return Key.B; + case XKey.c: + case XKey.C: + return Key.C; + case XKey.d: + case XKey.D: + return Key.D; + case XKey.e: + case XKey.E: + return Key.E; + case XKey.f: + case XKey.F: + return Key.F; + case XKey.g: + case XKey.G: + return Key.G; + case XKey.h: + case XKey.H: + return Key.H; + case XKey.i: + case XKey.I: + return Key.I; + case XKey.j: + case XKey.J: + return Key.J; + case XKey.k: + case XKey.K: + return Key.K; + case XKey.l: + case XKey.L: + return Key.L; + case XKey.m: + case XKey.M: + return Key.M; + case XKey.n: + case XKey.N: + return Key.N; + case XKey.o: + case XKey.O: + return Key.O; + case XKey.p: + case XKey.P: + return Key.P; + case XKey.q: + case XKey.Q: + return Key.Q; + case XKey.r: + case XKey.R: + return Key.R; + case XKey.s: + case XKey.S: + return Key.S; + case XKey.t: + case XKey.T: + return Key.T; + case XKey.u: + case XKey.U: + return Key.U; + case XKey.v: + case XKey.V: + return Key.V; + case XKey.w: + case XKey.W: + return Key.W; + case XKey.x: + case XKey.X: + return Key.X; + case XKey.y: + case XKey.Y: + return Key.Y; + case XKey.z: + case XKey.Z: + return Key.Z; + + case XKey.Number0: + return Key.Number0; + case XKey.Number1: + return Key.Number1; + case XKey.Number2: + return Key.Number2; + case XKey.Number3: + return Key.Number3; + case XKey.Number4: + return Key.Number4; + case XKey.Number5: + return Key.Number5; + case XKey.Number6: + return Key.Number6; + case XKey.Number7: + return Key.Number7; + case XKey.Number8: + return Key.Number8; + case XKey.Number9: + return Key.Number9; + + case XKey.KP_0: + return Key.Keypad0; + case XKey.KP_1: + return Key.Keypad1; + case XKey.KP_2: + return Key.Keypad2; + case XKey.KP_3: + return Key.Keypad3; + case XKey.KP_4: + return Key.Keypad4; + case XKey.KP_5: + return Key.Keypad5; + case XKey.KP_6: + return Key.Keypad6; + case XKey.KP_7: + return Key.Keypad7; + case XKey.KP_8: + return Key.Keypad8; + case XKey.KP_9: + return Key.Keypad9; + + case XKey.Pause: + return Key.Pause; + case XKey.Break: + return Key.Pause; + case XKey.Scroll_Lock: + return Key.Pause; + case XKey.Insert: + return Key.PrintScreen; + case XKey.Print: + return Key.PrintScreen; + case XKey.Sys_Req: + return Key.PrintScreen; + + case XKey.backslash: + return Key.BackSlash; + case XKey.bar: + return Key.BackSlash; + case XKey.braceleft: + return Key.BracketLeft; + case XKey.bracketleft: + return Key.BracketLeft; + case XKey.braceright: + return Key.BracketRight; + case XKey.bracketright: + return Key.BracketRight; + case XKey.colon: + return Key.Semicolon; + case XKey.semicolon: + return Key.Semicolon; + case XKey.quoteright: + return Key.Quote; + case XKey.quotedbl: + return Key.Quote; + case XKey.quoteleft: + return Key.Tilde; + case XKey.asciitilde: + return Key.Tilde; + + case XKey.comma: + return Key.Comma; + case XKey.less: + return Key.Comma; + case XKey.period: + return Key.Period; + case XKey.greater: + return Key.Period; + case XKey.slash: + return Key.Slash; + case XKey.question: + return Key.Slash; + + case XKey.Left: + return Key.Left; + case XKey.Down: + return Key.Down; + case XKey.Right: + return Key.Right; + case XKey.Up: + return Key.Up; + + case XKey.Delete: + return Key.Delete; + case XKey.Home: + return Key.Home; + case XKey.End: + return Key.End; + //case XKey.Prior: return Key.PageUp; // XKey.Prior == XKey.Page_Up + case XKey.Page_Up: + return Key.PageUp; + case XKey.Page_Down: + return Key.PageDown; + //case XKey.Next: return Key.PageDown; // XKey.Next == XKey.Page_Down + + case XKey.KP_Add: + return Key.KeypadAdd; + case XKey.KP_Subtract: + return Key.KeypadSubtract; + case XKey.KP_Multiply: + return Key.KeypadMultiply; + case XKey.KP_Divide: + return Key.KeypadDivide; + case XKey.KP_Decimal: + return Key.KeypadDecimal; + case XKey.KP_Insert: + return Key.Keypad0; + case XKey.KP_End: + return Key.Keypad1; + case XKey.KP_Down: + return Key.Keypad2; + case XKey.KP_Page_Down: + return Key.Keypad3; + case XKey.KP_Left: + return Key.Keypad4; + case XKey.KP_Right: + return Key.Keypad6; + case XKey.KP_Home: + return Key.Keypad7; + case XKey.KP_Up: + return Key.Keypad8; + case XKey.KP_Page_Up: + return Key.Keypad9; + case XKey.KP_Delete: + return Key.KeypadDecimal; + case XKey.KP_Enter: + return Key.KeypadEnter; + default: + return Key.Unknown; + } + } + + bool TranslateKeyEvent(ref XKeyEvent e, out Key key) + { + if (xkb_supported) + { + return TranslateKeyXkb(e.display, e.keycode, out key); + } + else + { + return TranslateKeyX11(ref e, out key); + } + } + + bool TranslateKeyX11(ref XKeyEvent e, out Key key) + { + XKey keysym = (XKey)API.LookupKeysym(ref e, 0); + XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1); + key = X11KeyMap.TranslateXKey(keysym); + if (key == Key.Unknown) + { + key = X11KeyMap.TranslateXKey(keysym2); + } + if (key == Key.Unknown) + { + Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2); + } + + return key != Key.Unknown; + } + +<<<<<<< HEAD + internal static MouseButton TranslateButton(int button, out float wheelx, out float wheely) +======= + bool TranslateKeyXkb(IntPtr display, int keycode, out Key key) + { + if (keycode < 8 || keycode > 255) + { + key = Key.Unknown; + return false; + } + + // Translate the numeric keypad using the secondary group + // (equivalent to NumLock = on) + XKey keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 1); + switch (keysym) + { + case XKey.KP_0: key = Key.Keypad0; return true; + case XKey.KP_1: key = Key.Keypad1; return true; + case XKey.KP_2: key = Key.Keypad2; return true; + case XKey.KP_3: key = Key.Keypad3; return true; + case XKey.KP_4: key = Key.Keypad4; return true; + case XKey.KP_5: key = Key.Keypad5; return true; + case XKey.KP_6: key = Key.Keypad6; return true; + case XKey.KP_7: key = Key.Keypad7; return true; + case XKey.KP_8: key = Key.Keypad8; return true; + case XKey.KP_9: key = Key.Keypad9; return true; + case XKey.KP_Separator: + case XKey.KP_Decimal: key = Key.KeypadDecimal; return true; + case XKey.KP_Equal: key = Key.Unknown; return false; // Todo: fixme + case XKey.KP_Enter: key = Key.KeypadEnter; return true; + } + + // Translate non-alphanumeric keys using the primary group + keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 0); + key = TranslateXKey(keysym); + return key != Key.Unknown; + } + + internal bool TranslateKey(int keycode, out Key key) + { + if (keycode < 0 || keycode > 255) + { + key = Key.Unknown; + } + else + { + key = keycodes[keycode]; + } + return key != Key.Unknown; + } + + internal bool TranslateKey(ref XKeyEvent e, out Key key) + { + return TranslateKey(e.keycode, out key); + + } + + internal static MouseButton TranslateButton(int button, out int wheelx, out int wheely) +>>>>>>> [X11] Use XKB for layout-independent input + { + wheelx = 0; + wheely = 0; + + switch (button) + { + case 1: return MouseButton.Left; + case 2: return MouseButton.Middle; + case 3: return MouseButton.Right; + case 4: wheely = +1; return MouseButton.LastButton; + case 5: wheely = -1; return MouseButton.LastButton; + case 6: wheelx = +1; return MouseButton.LastButton; + case 7: wheelx = -1; return MouseButton.LastButton; + case 8: return MouseButton.Button1; + case 9: return MouseButton.Button2; + case 10: return MouseButton.Button3; + case 11: return MouseButton.Button4; + case 12: return MouseButton.Button5; + case 13: return MouseButton.Button6; + case 14: return MouseButton.Button7; + default: return MouseButton.LastButton; + } + } + } +} From fd3ac1e4cc1cf7dc7a23ba8c925b4c82c7d60eea Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 19 May 2014 12:34:09 +0200 Subject: [PATCH 3/3] Removed file committed by mistake --- Source/OpenTK/Platform/X11/X11KeyMap.cs.orig | 727 ------------------- 1 file changed, 727 deletions(-) delete mode 100644 Source/OpenTK/Platform/X11/X11KeyMap.cs.orig diff --git a/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig b/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig deleted file mode 100644 index 5846c031..00000000 --- a/Source/OpenTK/Platform/X11/X11KeyMap.cs.orig +++ /dev/null @@ -1,727 +0,0 @@ -#region License -// -// Xkb.cs -// -// Author: -// Stefanos Apostolopoulos -// -// 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. -// -#endregion - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using OpenTK.Input; - -namespace OpenTK.Platform.X11 -{ - class X11KeyMap - { - // Keycode lookup table for current layout - readonly Key[] keycodes = new Key[256]; - readonly bool xkb_supported; - - internal X11KeyMap(IntPtr display) - { - xkb_supported = Xkb.IsSupported(display); - if (xkb_supported) - { - RefreshKeycodes(display); - } - } - - // Refreshes the keycodes lookup table based - // on the current keyboard layout. - internal void RefreshKeycodes(IntPtr display) - { - // Approach inspired by GLFW: http://www.glfw.org/ - // Huge props to the GLFW team! - if (xkb_supported) - { - unsafe - { - // Xkb.GetKeyboard appears to be broken (multiple bug reports across distros) - // so use Xkb.AllocKeyboard with Xkb.GetNames instead. - XkbDesc* keyboard = Xkb.AllocKeyboard(display); - if (keyboard != null) - { - Xkb.GetNames(display, XkbNamesMask.All, keyboard); - - for (int i = 0; i < keycodes.Length; i++) - { - keycodes[i] = Key.Unknown; - } - - // Map all alphanumeric keys of this layout - // Symbols are handled in GetKey() instead. - for (int i = keyboard->min_key_code; i <= keyboard->max_key_code; ++i) - { - string name = new string((sbyte*)keyboard->names->keys[i].name, 0, Xkb.KeyNameLength); - - Key key = Key.Unknown; - switch (name) - { - case "TLDE": - key = Key.Tilde; - break; - case "AE01": - key = Key.Number1; - break; - case "AE02": - key = Key.Number2; - break; - case "AE03": - key = Key.Number3; - break; - case "AE04": - key = Key.Number4; - break; - case "AE05": - key = Key.Number5; - break; - case "AE06": - key = Key.Number6; - break; - case "AE07": - key = Key.Number7; - break; - case "AE08": - key = Key.Number8; - break; - case "AE09": - key = Key.Number9; - break; - case "AE10": - key = Key.Number0; - break; - case "AE11": - key = Key.Minus; - break; - case "AE12": - key = Key.Plus; - break; - case "AD01": - key = Key.Q; - break; - case "AD02": - key = Key.W; - break; - case "AD03": - key = Key.E; - break; - case "AD04": - key = Key.R; - break; - case "AD05": - key = Key.T; - break; - case "AD06": - key = Key.Y; - break; - case "AD07": - key = Key.U; - break; - case "AD08": - key = Key.I; - break; - case "AD09": - key = Key.O; - break; - case "AD10": - key = Key.P; - break; - case "AD11": - key = Key.BracketLeft; - break; - case "AD12": - key = Key.BracketRight; - break; - case "AC01": - key = Key.A; - break; - case "AC02": - key = Key.S; - break; - case "AC03": - key = Key.D; - break; - case "AC04": - key = Key.F; - break; - case "AC05": - key = Key.G; - break; - case "AC06": - key = Key.H; - break; - case "AC07": - key = Key.J; - break; - case "AC08": - key = Key.K; - break; - case "AC09": - key = Key.L; - break; - case "AC10": - key = Key.Semicolon; - break; - case "AC11": - key = Key.Quote; - break; - case "AB01": - key = Key.Z; - break; - case "AB02": - key = Key.X; - break; - case "AB03": - key = Key.C; - break; - case "AB04": - key = Key.V; - break; - case "AB05": - key = Key.B; - break; - case "AB06": - key = Key.N; - break; - case "AB07": - key = Key.M; - break; - case "AB08": - key = Key.Comma; - break; - case "AB09": - key = Key.Period; - break; - case "AB10": - key = Key.Slash; - break; - case "BKSL": - key = Key.BackSlash; - break; - case "LSGT": - key = Key.Unknown; - break; - default: - key = Key.Unknown; - break; - } - - keycodes[i] = key; - } - - Xkb.FreeKeyboard(keyboard, 0, true); - } - } - } - - // Translate unknown keys (and symbols) using - // regular layout-dependent GetKey() - for (int i = 0; i < 256; i++) - { - if (keycodes[i] == Key.Unknown) - { - // TranslateKeyCode expects a XKeyEvent structure - // Make one up - XKeyEvent e = new XKeyEvent(); - e.display = display; - e.keycode = i; - Key key = Key.Unknown; - if (TranslateKeyEvent(ref e, out key)) - { - keycodes[i] = key; - } - } - } - } - - static Key TranslateXKey(XKey key) - { - switch (key) - { - case XKey.Escape: - return Key.Escape; - case XKey.Return: - return Key.Enter; - case XKey.space: - return Key.Space; - case XKey.BackSpace: - return Key.BackSpace; - - case XKey.Shift_L: - return Key.ShiftLeft; - case XKey.Shift_R: - return Key.ShiftRight; - case XKey.Alt_L: - return Key.AltLeft; - case XKey.Alt_R: - return Key.AltRight; - case XKey.Control_L: - return Key.ControlLeft; - case XKey.Control_R: - return Key.ControlRight; - case XKey.Super_L: - return Key.WinLeft; - case XKey.Super_R: - return Key.WinRight; - case XKey.Meta_L: - return Key.WinLeft; - case XKey.Meta_R: - return Key.WinRight; - case XKey.ISO_Level3_Shift: - return Key.AltRight; // Normally AltGr - - case XKey.Menu: - return Key.Menu; - case XKey.Tab: - return Key.Tab; - case XKey.minus: - return Key.Minus; - case XKey.plus: - return Key.Plus; - case XKey.equal: - return Key.Plus; - - case XKey.Caps_Lock: - return Key.CapsLock; - case XKey.Num_Lock: - return Key.NumLock; - - case XKey.F1: - return Key.F1; - case XKey.F2: - return Key.F2; - case XKey.F3: - return Key.F3; - case XKey.F4: - return Key.F4; - case XKey.F5: - return Key.F5; - case XKey.F6: - return Key.F6; - case XKey.F7: - return Key.F7; - case XKey.F8: - return Key.F8; - case XKey.F9: - return Key.F9; - case XKey.F10: - return Key.F10; - case XKey.F11: - return Key.F11; - case XKey.F12: - return Key.F12; - case XKey.F13: - return Key.F13; - case XKey.F14: - return Key.F14; - case XKey.F15: - return Key.F15; - case XKey.F16: - return Key.F16; - case XKey.F17: - return Key.F17; - case XKey.F18: - return Key.F18; - case XKey.F19: - return Key.F19; - case XKey.F20: - return Key.F20; - case XKey.F21: - return Key.F21; - case XKey.F22: - return Key.F22; - case XKey.F23: - return Key.F23; - case XKey.F24: - return Key.F24; - case XKey.F25: - return Key.F25; - case XKey.F26: - return Key.F26; - case XKey.F27: - return Key.F27; - case XKey.F28: - return Key.F28; - case XKey.F29: - return Key.F29; - case XKey.F30: - return Key.F30; - case XKey.F31: - return Key.F31; - case XKey.F32: - return Key.F32; - case XKey.F33: - return Key.F33; - case XKey.F34: - return Key.F34; - case XKey.F35: - return Key.F35; - - case XKey.a: - case XKey.A: - return Key.A; - case XKey.b: - case XKey.B: - return Key.B; - case XKey.c: - case XKey.C: - return Key.C; - case XKey.d: - case XKey.D: - return Key.D; - case XKey.e: - case XKey.E: - return Key.E; - case XKey.f: - case XKey.F: - return Key.F; - case XKey.g: - case XKey.G: - return Key.G; - case XKey.h: - case XKey.H: - return Key.H; - case XKey.i: - case XKey.I: - return Key.I; - case XKey.j: - case XKey.J: - return Key.J; - case XKey.k: - case XKey.K: - return Key.K; - case XKey.l: - case XKey.L: - return Key.L; - case XKey.m: - case XKey.M: - return Key.M; - case XKey.n: - case XKey.N: - return Key.N; - case XKey.o: - case XKey.O: - return Key.O; - case XKey.p: - case XKey.P: - return Key.P; - case XKey.q: - case XKey.Q: - return Key.Q; - case XKey.r: - case XKey.R: - return Key.R; - case XKey.s: - case XKey.S: - return Key.S; - case XKey.t: - case XKey.T: - return Key.T; - case XKey.u: - case XKey.U: - return Key.U; - case XKey.v: - case XKey.V: - return Key.V; - case XKey.w: - case XKey.W: - return Key.W; - case XKey.x: - case XKey.X: - return Key.X; - case XKey.y: - case XKey.Y: - return Key.Y; - case XKey.z: - case XKey.Z: - return Key.Z; - - case XKey.Number0: - return Key.Number0; - case XKey.Number1: - return Key.Number1; - case XKey.Number2: - return Key.Number2; - case XKey.Number3: - return Key.Number3; - case XKey.Number4: - return Key.Number4; - case XKey.Number5: - return Key.Number5; - case XKey.Number6: - return Key.Number6; - case XKey.Number7: - return Key.Number7; - case XKey.Number8: - return Key.Number8; - case XKey.Number9: - return Key.Number9; - - case XKey.KP_0: - return Key.Keypad0; - case XKey.KP_1: - return Key.Keypad1; - case XKey.KP_2: - return Key.Keypad2; - case XKey.KP_3: - return Key.Keypad3; - case XKey.KP_4: - return Key.Keypad4; - case XKey.KP_5: - return Key.Keypad5; - case XKey.KP_6: - return Key.Keypad6; - case XKey.KP_7: - return Key.Keypad7; - case XKey.KP_8: - return Key.Keypad8; - case XKey.KP_9: - return Key.Keypad9; - - case XKey.Pause: - return Key.Pause; - case XKey.Break: - return Key.Pause; - case XKey.Scroll_Lock: - return Key.Pause; - case XKey.Insert: - return Key.PrintScreen; - case XKey.Print: - return Key.PrintScreen; - case XKey.Sys_Req: - return Key.PrintScreen; - - case XKey.backslash: - return Key.BackSlash; - case XKey.bar: - return Key.BackSlash; - case XKey.braceleft: - return Key.BracketLeft; - case XKey.bracketleft: - return Key.BracketLeft; - case XKey.braceright: - return Key.BracketRight; - case XKey.bracketright: - return Key.BracketRight; - case XKey.colon: - return Key.Semicolon; - case XKey.semicolon: - return Key.Semicolon; - case XKey.quoteright: - return Key.Quote; - case XKey.quotedbl: - return Key.Quote; - case XKey.quoteleft: - return Key.Tilde; - case XKey.asciitilde: - return Key.Tilde; - - case XKey.comma: - return Key.Comma; - case XKey.less: - return Key.Comma; - case XKey.period: - return Key.Period; - case XKey.greater: - return Key.Period; - case XKey.slash: - return Key.Slash; - case XKey.question: - return Key.Slash; - - case XKey.Left: - return Key.Left; - case XKey.Down: - return Key.Down; - case XKey.Right: - return Key.Right; - case XKey.Up: - return Key.Up; - - case XKey.Delete: - return Key.Delete; - case XKey.Home: - return Key.Home; - case XKey.End: - return Key.End; - //case XKey.Prior: return Key.PageUp; // XKey.Prior == XKey.Page_Up - case XKey.Page_Up: - return Key.PageUp; - case XKey.Page_Down: - return Key.PageDown; - //case XKey.Next: return Key.PageDown; // XKey.Next == XKey.Page_Down - - case XKey.KP_Add: - return Key.KeypadAdd; - case XKey.KP_Subtract: - return Key.KeypadSubtract; - case XKey.KP_Multiply: - return Key.KeypadMultiply; - case XKey.KP_Divide: - return Key.KeypadDivide; - case XKey.KP_Decimal: - return Key.KeypadDecimal; - case XKey.KP_Insert: - return Key.Keypad0; - case XKey.KP_End: - return Key.Keypad1; - case XKey.KP_Down: - return Key.Keypad2; - case XKey.KP_Page_Down: - return Key.Keypad3; - case XKey.KP_Left: - return Key.Keypad4; - case XKey.KP_Right: - return Key.Keypad6; - case XKey.KP_Home: - return Key.Keypad7; - case XKey.KP_Up: - return Key.Keypad8; - case XKey.KP_Page_Up: - return Key.Keypad9; - case XKey.KP_Delete: - return Key.KeypadDecimal; - case XKey.KP_Enter: - return Key.KeypadEnter; - default: - return Key.Unknown; - } - } - - bool TranslateKeyEvent(ref XKeyEvent e, out Key key) - { - if (xkb_supported) - { - return TranslateKeyXkb(e.display, e.keycode, out key); - } - else - { - return TranslateKeyX11(ref e, out key); - } - } - - bool TranslateKeyX11(ref XKeyEvent e, out Key key) - { - XKey keysym = (XKey)API.LookupKeysym(ref e, 0); - XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1); - key = X11KeyMap.TranslateXKey(keysym); - if (key == Key.Unknown) - { - key = X11KeyMap.TranslateXKey(keysym2); - } - if (key == Key.Unknown) - { - Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2); - } - - return key != Key.Unknown; - } - -<<<<<<< HEAD - internal static MouseButton TranslateButton(int button, out float wheelx, out float wheely) -======= - bool TranslateKeyXkb(IntPtr display, int keycode, out Key key) - { - if (keycode < 8 || keycode > 255) - { - key = Key.Unknown; - return false; - } - - // Translate the numeric keypad using the secondary group - // (equivalent to NumLock = on) - XKey keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 1); - switch (keysym) - { - case XKey.KP_0: key = Key.Keypad0; return true; - case XKey.KP_1: key = Key.Keypad1; return true; - case XKey.KP_2: key = Key.Keypad2; return true; - case XKey.KP_3: key = Key.Keypad3; return true; - case XKey.KP_4: key = Key.Keypad4; return true; - case XKey.KP_5: key = Key.Keypad5; return true; - case XKey.KP_6: key = Key.Keypad6; return true; - case XKey.KP_7: key = Key.Keypad7; return true; - case XKey.KP_8: key = Key.Keypad8; return true; - case XKey.KP_9: key = Key.Keypad9; return true; - case XKey.KP_Separator: - case XKey.KP_Decimal: key = Key.KeypadDecimal; return true; - case XKey.KP_Equal: key = Key.Unknown; return false; // Todo: fixme - case XKey.KP_Enter: key = Key.KeypadEnter; return true; - } - - // Translate non-alphanumeric keys using the primary group - keysym = Xkb.KeycodeToKeysym(display, keycode, 0, 0); - key = TranslateXKey(keysym); - return key != Key.Unknown; - } - - internal bool TranslateKey(int keycode, out Key key) - { - if (keycode < 0 || keycode > 255) - { - key = Key.Unknown; - } - else - { - key = keycodes[keycode]; - } - return key != Key.Unknown; - } - - internal bool TranslateKey(ref XKeyEvent e, out Key key) - { - return TranslateKey(e.keycode, out key); - - } - - internal static MouseButton TranslateButton(int button, out int wheelx, out int wheely) ->>>>>>> [X11] Use XKB for layout-independent input - { - wheelx = 0; - wheely = 0; - - switch (button) - { - case 1: return MouseButton.Left; - case 2: return MouseButton.Middle; - case 3: return MouseButton.Right; - case 4: wheely = +1; return MouseButton.LastButton; - case 5: wheely = -1; return MouseButton.LastButton; - case 6: wheelx = +1; return MouseButton.LastButton; - case 7: wheelx = -1; return MouseButton.LastButton; - case 8: return MouseButton.Button1; - case 9: return MouseButton.Button2; - case 10: return MouseButton.Button3; - case 11: return MouseButton.Button4; - case 12: return MouseButton.Button5; - case 13: return MouseButton.Button6; - case 14: return MouseButton.Button7; - default: return MouseButton.LastButton; - } - } - } -}