Work on MouseDriver. Windows raw driver works.

This commit is contained in:
the_fiddler 2007-09-21 20:34:07 +00:00
parent 8bbaede72e
commit 39fa68a29f
7 changed files with 445 additions and 23 deletions

View file

@ -10,7 +10,23 @@ using System.Text;
namespace OpenTK.Input namespace OpenTK.Input
{ {
interface IMouse : IInputDevice public interface IMouse : IInputDevice
{ {
int NumberOfButtons { get; }
int NumberOfWheels { get; }
IntPtr DeviceID { get; }
int Wheel { get; }
int X { get; }
int Y { get; }
int DeltaX { get; }
int DeltaY { get; }
event MouseMoveEvent Move;
event MouseButtonDownEvent ButtonDown;
event MouseButtonUpEvent ButtonUp;
} }
public delegate void MouseMoveEvent(IMouse sender, MouseMoveData key);
public delegate void MouseButtonDownEvent(IMouse sender, MouseButton button);
public delegate void MouseButtonUpEvent(IMouse sender, MouseButton button);
} }

View file

@ -12,6 +12,16 @@ namespace OpenTK.Input
{ {
public interface IMouseDriver public interface IMouseDriver
{ {
IList<OpenTK.Input.Mouse> Mouse { get; } /// <summary>
/// Gets the list of available mouse devices.
/// </summary>
IList<Mouse> Mouse { get; }
/*
/// <summary>
/// Registers available mouse devices.
/// </summary>
/// <returns>The number of devices registered.</returns>
int RegisterDevices();
*/
} }
} }

View file

@ -10,13 +10,20 @@ using System.Text;
namespace OpenTK.Input namespace OpenTK.Input
{ {
public class Mouse : IMouse public sealed class Mouse : IMouse
{ {
private string description;
private int numButtons, numWheels;
private IntPtr id;
private bool[] button = new bool[(int)MouseButton.LastButton];
private int wheel, x, y, delta_x, delta_y;
#region --- IInputDevice Members --- #region --- IInputDevice Members ---
public string Description public string Description
{ {
get { throw new Exception("The method or operation is not implemented."); } get { return description; }
internal set { description = value; }
} }
public InputDeviceType DeviceType public InputDeviceType DeviceType
@ -25,5 +32,173 @@ namespace OpenTK.Input
} }
#endregion #endregion
#region --- IMouse Members ---
public int NumberOfButtons
{
get { return numButtons; }
internal set { numButtons = value; }
}
public int NumberOfWheels
{
get { return numWheels; }
internal set { numWheels = value; }
}
public IntPtr DeviceID
{
get { return id; }
internal set { id = value; }
}
public int Wheel
{
get { return wheel; }
internal set { wheel = value; }
}
public int X
{
get { return x; }
internal set { x = value; }
}
public int Y
{
get { return y; }
internal set { y = value; }
}
public int DeltaX
{
get { return delta_x; }
internal set { delta_x = value; }
}
public int DeltaY
{
get { return delta_y; }
internal set { delta_y = value; }
}
public event MouseMoveEvent Move;
public event MouseButtonDownEvent ButtonDown;
public event MouseButtonUpEvent ButtonUp;
#endregion
#region public bool this[MouseButton b]
public bool this[MouseButton b]
{
internal set
{
button[(int)b] = value;
}
get
{
return button[(int)b];
}
}
#endregion
}
public enum MouseButton
{
Left = 0,
Middle,
Right,
Button1,
Button2,
Button3,
Button4,
Button5,
Button6,
Button7,
Button8,
Button9,
LastButton
}
public class MouseWheel
{
private int position;
private int delta;
/// <summary>
/// Gets the absolute position of the mouse wheel.
/// </summary>
public int Position
{
get { return position; }
internal set { position = value; }
}
/// <summary>
/// Gets the relative movement of the mouse wheel.
/// </summary>
public int Delta
{
get { return delta; }
internal set { delta = value; }
}
}
public class MouseMoveData
{
private int x;
private int y;
private int deltaX;
private int deltaY;
private MouseWheel wheel;
/// <summary>
/// Gets the absolute X position of the mouse in screen pixel coordinates.
/// </summary>
public int X
{
get { return x; }
internal set { x = value; }
}
/// <summary>
/// Gets the absolute Y position of the mouse in screen pixel coordinates.
/// </summary>
public int Y
{
get { return y; }
internal set { y = value; }
}
/// <summary>
/// Gets the relative movement of the mouse in the X direction, in pixels.
/// </summary>
public int DeltaX
{
get { return deltaX; }
internal set { deltaX = value; }
}
/// <summary>
/// Gets the relative movement of the mouse in the Y direction, in pixels.
/// </summary>
public int DeltaY
{
get { return deltaY; }
internal set { deltaY = value; }
}
/// <summary>
/// Gets data relevant to the mouse wheel.
/// </summary>
public MouseWheel Wheel
{
get { return wheel; }
internal set { wheel = value; }
}
} }
} }

View file

@ -30,10 +30,11 @@ namespace OpenTK.Platform.Windows
private static int deviceCount; private static int deviceCount;
private WinRawKeyboard keyboardDriver; private WinRawKeyboard keyboardDriver;
private WinRawMouse mouseDriver;
#region --- Constructors --- #region --- Constructors ---
internal WinRawInput(WindowInfo parent) internal WinRawInput(IWindowInfo parent)
{ {
Debug.WriteLine("Initalizing windows raw input driver."); Debug.WriteLine("Initalizing windows raw input driver.");
Debug.Indent(); Debug.Indent();
@ -41,6 +42,7 @@ namespace OpenTK.Platform.Windows
AssignHandle(parent.Handle); AssignHandle(parent.Handle);
Debug.Print("Input window attached to parent {0}", parent); Debug.Print("Input window attached to parent {0}", parent);
keyboardDriver = new WinRawKeyboard(this.Handle); keyboardDriver = new WinRawKeyboard(this.Handle);
mouseDriver = new WinRawMouse(this.Handle);
Debug.Unindent(); Debug.Unindent();
} }
@ -94,12 +96,16 @@ namespace OpenTK.Platform.Windows
return; return;
case RawInputDeviceType.MOUSE: case RawInputDeviceType.MOUSE:
if (!mouseDriver.ProcessEvent(data))
API.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize); API.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize);
return; return;
case RawInputDeviceType.HID: case RawInputDeviceType.HID:
API.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize); API.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize);
return; return;
default:
break;
} }
} }
else else
@ -141,7 +147,7 @@ namespace OpenTK.Platform.Windows
public IList<Mouse> Mouse public IList<Mouse> Mouse
{ {
get { throw new Exception("The method or operation is not implemented."); } get { return mouseDriver.Mouse; }
} }
public void ProcessEvents() public void ProcessEvents()

View file

@ -7,10 +7,209 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using OpenTK.Input;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
class WinRawMouse internal class WinRawMouse : IMouseDriver, IDisposable
{
private List<Mouse> mice = new List<Mouse>();
private IntPtr window;
#region --- Constructors ---
internal WinRawMouse()
: this(IntPtr.Zero)
{ {
} }
internal WinRawMouse(IntPtr windowHandle)
{
Debug.WriteLine("Initializing mouse driver (WinRawMouse).");
Debug.Indent();
this.window = windowHandle;
RegisterDevices();
Debug.Unindent();
}
#endregion
#region --- IMouseDriver Members ---
public IList<Mouse> Mouse
{
get { return mice; }
}
public int RegisterDevices()
{
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
API.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover mouse devices:
for (int i = 0; i < count; i++)
{
uint size = 0;
API.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
API.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
if (name.ToLower().Contains("root"))
{
// This is a terminal services device, skip it.
continue;
}
else if (ridl[i].Type == RawInputDeviceType.MOUSE || ridl[i].Type == RawInputDeviceType.HID)
{
// This is a mouse or a USB mouse device. In the latter case, discover if it really is a
// mouse device by qeurying the registry.
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
string deviceDesc =
(string)regkey.GetValue("DeviceDesc");
string deviceClass =
(string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
{
OpenTK.Input.Mouse mouse = new OpenTK.Input.Mouse();
mouse.Description = deviceDesc;
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
API.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
mouse.NumberOfButtons = info.Device.Mouse.NumberOfButtons;
mouse.NumberOfWheels = info.Device.Mouse.HasHorizontalWheel ? 1 : 0;
mouse.DeviceID = ridl[i].Device;//(IntPtr)info.Device.Mouse.Id;
this.RegisterRawDevice(mouse);
mice.Add(mouse);
}
}
}
return count;
}
#endregion
#region internal void RegisterRawDevice(OpenTK.Input.Mouse mouse)
internal void RegisterRawDevice(OpenTK.Input.Mouse mouse)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Mouse is 1/2 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new RawInputDevice();
rid[0].UsagePage = 1;
rid[0].Usage = 2;
rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
rid[0].Target = window;
if (!API.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
throw new ApplicationException(
String.Format(
"Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(),
rid[0].ToString())
);
}
else
{
Debug.Print("Registered mouse {0}", mouse.ToString());
}
}
#endregion
#region internal bool ProcessEvent(API.RawInput rin)
/// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessEvent(RawInput rin)
{
Mouse mouse = mice.Find(delegate(Mouse m)
{
return m.DeviceID == rin.Header.Device;
});
switch (rin.Header.Type)
{
case RawInputDeviceType.MOUSE:
mouse[MouseButton.Left] = rin.Data.Mouse.ButtonFlags == RawInputMouseState.LEFT_BUTTON_DOWN;
mouse[MouseButton.Right] = rin.Data.Mouse.ButtonFlags == RawInputMouseState.RIGHT_BUTTON_DOWN;
mouse[MouseButton.Middle] = rin.Data.Mouse.ButtonFlags == RawInputMouseState.MIDDLE_BUTTON_DOWN;
mouse[MouseButton.Button1] = rin.Data.Mouse.ButtonFlags == RawInputMouseState.BUTTON_4_DOWN;
mouse[MouseButton.Button2] = rin.Data.Mouse.ButtonFlags == RawInputMouseState.BUTTON_5_DOWN;
if (rin.Data.Mouse.ButtonFlags == RawInputMouseState.WHEEL)
{
mouse.Wheel += rin.Data.Mouse.ButtonData;
}
if (rin.Data.Mouse.Flags == RawMouseFlags.MOUSE_MOVE_ABSOLUTE)
{
mouse.DeltaX = mouse.X - rin.Data.Mouse.LastX;
mouse.DeltaY = mouse.Y - rin.Data.Mouse.LastY;
mouse.X = rin.Data.Mouse.LastX;
mouse.Y = rin.Data.Mouse.LastY;
}
else if (rin.Data.Mouse.Flags == RawMouseFlags.MOUSE_MOVE_RELATIVE)
{
mouse.DeltaX = rin.Data.Mouse.LastX;
mouse.DeltaY = rin.Data.Mouse.LastY;
mouse.X += mouse.DeltaX;
mouse.Y += mouse.DeltaY;
}
return false;
default:
throw new ApplicationException("WinRawMouse driver received keyboard data.");
}
}
#endregion
#region --- IDisposable Members ---
public void Dispose()
{
//throw new Exception("The method or operation is not implemented.");
}
#endregion
}
} }

View file

@ -20,7 +20,8 @@ namespace OpenTK.Platform.X11
internal sealed class X11Input : IInputDriver internal sealed class X11Input : IInputDriver
{ {
private X11Keyboard keyboardDriver; private X11Keyboard keyboardDriver;
private WindowInfo window; private X11Mouse mouseDriver;
private X11.WindowInfo window;
XEvent e = new XEvent(); XEvent e = new XEvent();
@ -31,13 +32,13 @@ namespace OpenTK.Platform.X11
/// the main application window, which selects input events and routes them to /// the main application window, which selects input events and routes them to
/// the device specific drivers (Keyboard, Mouse, Hid). /// the device specific drivers (Keyboard, Mouse, Hid).
/// </summary> /// </summary>
/// <param name="parent"></param> /// <param name="attach">The window which the InputDriver will attach itself on.</param>
public X11Input(WindowInfo parent) public X11Input(IWindowInfo attach)
{ {
Debug.WriteLine("Initalizing X11 input driver."); Debug.WriteLine("Initalizing X11 input driver.");
Debug.Indent(); Debug.Indent();
if (parent == null) if (attach == null)
{ {
throw new ArgumentException("A valid parent window must be defined, in order to create an X11Input driver."); throw new ArgumentException("A valid parent window must be defined, in order to create an X11Input driver.");
} }
@ -82,10 +83,11 @@ namespace OpenTK.Platform.X11
keyboardDriver = new X11Keyboard(window); keyboardDriver = new X11Keyboard(window);
*/ */
window = new WindowInfo(parent); window = attach as Platform.WindowInfo ?? attach as X11.WindowInfo;
keyboardDriver = new X11Keyboard(parent);
// Todo: donparent's mask is now specified by hand, hard to keep in sync. keyboardDriver = new X11Keyboard(window);
API.SelectInput(parent.Display, parent.Handle, EventMask.StructureNotifyMask | // Todo: mask is now specified by hand, hard to keep in sync.
API.SelectInput(window.Display, window.Handle, EventMask.StructureNotifyMask |
EventMask.SubstructureNotifyMask | EventMask.ExposureMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask |
EventMask.KeyReleaseMask | EventMask.KeyPressMask); EventMask.KeyReleaseMask | EventMask.KeyPressMask);

View file

@ -7,10 +7,24 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using OpenTK.Input;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
class X11Mouse class X11Mouse : IMouseDriver
{ {
#region --- IMouseDriver Members ---
public IList<Mouse> Mouse
{
get { throw new Exception("The method or operation is not implemented."); }
}
public int RegisterDevices()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
} }
} }