From 00b5174f6348f3e86ee68512048ffb0e21b41b0c Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 18 Jul 2014 11:23:28 +0200 Subject: [PATCH] [Linux] Delay input device detection until a key is pressed --- Source/OpenTK/Platform/DeviceCollection.cs | 12 ++++++-- Source/OpenTK/Platform/Linux/LinuxInput.cs | 48 +++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Source/OpenTK/Platform/DeviceCollection.cs b/Source/OpenTK/Platform/DeviceCollection.cs index 8229c29..0c70f35 100644 --- a/Source/OpenTK/Platform/DeviceCollection.cs +++ b/Source/OpenTK/Platform/DeviceCollection.cs @@ -77,14 +77,22 @@ namespace OpenTK.Platform public void Remove(int id) { - if (!Map.ContainsKey(id)) + if (!TryRemove(id)) { Debug.Print("Invalid DeviceCollection<{0}> id: {1}", typeof(T).FullName, id); - return; + } + } + + public bool TryRemove(int id) + { + if (!Map.ContainsKey(id)) + { + return false; } Devices[Map[id]] = default(T); Map.Remove(id); + return true; } public T FromIndex(int index) diff --git a/Source/OpenTK/Platform/Linux/LinuxInput.cs b/Source/OpenTK/Platform/Linux/LinuxInput.cs index c3f435f..ddca85f 100644 --- a/Source/OpenTK/Platform/Linux/LinuxInput.cs +++ b/Source/OpenTK/Platform/Linux/LinuxInput.cs @@ -117,7 +117,6 @@ namespace OpenTK.Platform.Linux public KeyboardDevice(IntPtr device, int id) : base(device, id) { - State.SetIsConnected(true); } } @@ -128,13 +127,23 @@ namespace OpenTK.Platform.Linux public MouseDevice(IntPtr device, int id) : base(device, id) { - State.SetIsConnected(true); } } static readonly object Sync = new object(); static readonly Key[] KeyMap = Evdev.KeyMap; static long DeviceFDCount; + + // libinput returns various devices with keyboard/pointer even though + // they are not traditional keyboards/mice (for example "Integrated Camera" + // can be detected as a keyboard.) + // Since there is no API to retrieve actual device capabilities, + // we add all detected devices to a "candidate" list and promote them + // to an actual keyboard/mouse only when we receive a valid input event. + // This is far from optimal, but it appears to be the only viable solution + // unless a new API is added to libinput. + DeviceCollection KeyboardCandidates = new DeviceCollection(); + DeviceCollection MouseCandidates = new DeviceCollection(); DeviceCollection Keyboards = new DeviceCollection(); DeviceCollection Mice = new DeviceCollection(); @@ -399,7 +408,7 @@ namespace OpenTK.Platform.Linux if (LibInput.DeviceHasCapability(device, DeviceCapability.Keyboard)) { KeyboardDevice keyboard = new KeyboardDevice(device, Keyboards.Count); - Keyboards.Add(keyboard.Id, keyboard); + KeyboardCandidates.Add(keyboard.Id, keyboard); Debug.Print("[Input] Added keyboard device {0} '{1}' on '{2}' ('{3}')", keyboard.Id, keyboard.Name, keyboard.LogicalSeatName, keyboard.PhysicalSeatName); } @@ -407,7 +416,7 @@ namespace OpenTK.Platform.Linux if (LibInput.DeviceHasCapability(device, DeviceCapability.Mouse)) { MouseDevice mouse = new MouseDevice(device, Mice.Count); - Mice.Add(mouse.Id, mouse); + MouseCandidates.Add(mouse.Id, mouse); Debug.Print("[Input] Added mouse device {0} '{1}' on '{2}' ('{3}')", mouse.Id, mouse.Name, mouse.LogicalSeatName, mouse.PhysicalSeatName); } @@ -423,13 +432,15 @@ namespace OpenTK.Platform.Linux if (LibInput.DeviceHasCapability(device, DeviceCapability.Keyboard)) { int id = GetId(device); - Keyboards.Remove(id); + Keyboards.TryRemove(id); + KeyboardCandidates.TryRemove(id); } if (LibInput.DeviceHasCapability(device, DeviceCapability.Mouse)) { int id = GetId(device); - Mice.Remove(id); + Mice.TryRemove(id); + MouseCandidates.TryRemove(id); } } @@ -437,6 +448,9 @@ namespace OpenTK.Platform.Linux { if (device != null) { + device.State.SetIsConnected(true); + Debug.Print("[Input] Added keyboard {0}", device.Id); + Key key = Key.Unknown; uint raw = e.Key; if (raw >= 0 && raw < KeyMap.Length) @@ -457,6 +471,8 @@ namespace OpenTK.Platform.Linux { if (mouse != null) { + mouse.State.SetIsConnected(true); + double value = e.AxisValue; PointerAxis axis = e.Axis; switch (axis) @@ -480,6 +496,8 @@ namespace OpenTK.Platform.Linux { if (mouse != null) { + mouse.State.SetIsConnected(true); + MouseButton button = Evdev.GetMouseButton(e.Button); ButtonState state = e.ButtonState; mouse.State[(MouseButton)button] = state == ButtonState.Pressed; @@ -491,6 +509,7 @@ namespace OpenTK.Platform.Linux Vector2 delta = new Vector2((float)e.X, (float)e.Y); if (mouse != null) { + mouse.State.SetIsConnected(true); mouse.State.Position += delta; } @@ -504,6 +523,7 @@ namespace OpenTK.Platform.Linux { if (mouse != null) { + mouse.State.SetIsConnected(true); mouse.State.Position = new Vector2(e.X, e.Y); } @@ -521,8 +541,12 @@ namespace OpenTK.Platform.Linux KeyboardDevice GetKeyboard(IntPtr device) { int id = GetId(device); - KeyboardDevice keyboard = Keyboards.FromHardwareId(id); - if (keyboard == null) + KeyboardDevice keyboard = KeyboardCandidates.FromHardwareId(id); + if (keyboard != null) + { + Keyboards.Add(id, keyboard); + } + else { Debug.Print("[Input] Keyboard {0} does not exist in device list.", id); } @@ -532,8 +556,12 @@ namespace OpenTK.Platform.Linux MouseDevice GetMouse(IntPtr device) { int id = GetId(device); - MouseDevice mouse = Mice.FromHardwareId(id); - if (mouse == null) + MouseDevice mouse = MouseCandidates.FromHardwareId(id); + if (mouse != null) + { + Mice.Add(id, mouse); + } + else { Debug.Print("[Input] Mouse {0} does not exist in device list.", id); } -- 2.7.4