diff --git a/Source/OpenTK/Input/ButtonState.cs b/Source/OpenTK/Input/ButtonState.cs new file mode 100644 index 00000000..597611f8 --- /dev/null +++ b/Source/OpenTK/Input/ButtonState.cs @@ -0,0 +1,46 @@ + #region License + // + // The Open Toolkit Library License + // + // Copyright (c) 2006 - 2010 the Open Toolkit library. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to deal + // in the Software without restriction, including without limitation the rights to + // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + // the Software, and to permit persons to whom the Software is furnished to do + // so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in all + // copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + // OTHER DEALINGS IN THE SOFTWARE. + // + #endregion + +namespace OpenTK.Input +{ + /// + /// Enumerates possible mouse button states. + /// + public enum ButtonState + { + /// + /// Indicates that a mouse button is released. + /// + Released = 0, + + /// + /// Indicates that a mouse button is pressed. + /// + Pressed = 1 + } +} + diff --git a/Source/OpenTK/Input/MouseState.cs b/Source/OpenTK/Input/MouseState.cs index 77d044fb..feae30d5 100644 --- a/Source/OpenTK/Input/MouseState.cs +++ b/Source/OpenTK/Input/MouseState.cs @@ -42,6 +42,8 @@ namespace OpenTK.Input const int NumInts = ((int)MouseButton.LastButton + 31) / 32; // The following line triggers bogus CS0214 in gmcs 2.0.1, sigh... unsafe fixed int Buttons[NumInts]; + int x, y; + float wheel; #endregion @@ -51,7 +53,7 @@ namespace OpenTK.Input /// Gets a indicating whether this button is down. /// /// The to check. - public bool IsKeyDown(MouseButton button) + public bool IsButtonDown(MouseButton button) { return ReadBit((int)button); } @@ -60,11 +62,151 @@ namespace OpenTK.Input /// Gets a indicating whether this button is up. /// /// The to check. - public bool IsKeyUp(MouseButton button) + public bool IsButtonUp(MouseButton button) { return !ReadBit((int)button); } + /// + /// Gets the absolute wheel position in integer units. + /// To support high-precision mice, it is recommended to use instead. + /// + public int Wheel + { + get { return (int)Math.Round(wheel, MidpointRounding.AwayFromZero); } + } + + /// + /// Gets the absolute wheel position in floating-point units. + /// + public float WheelPrecise + { + get { return wheel; } + internal set + { + wheel = value; + } + } + + /// + /// Gets an integer representing the absolute x position of the pointer, in window pixel coordinates. + /// + public int X + { + get { return x; } + internal set { x = value; } + } + + /// + /// Gets an integer representing the absolute y position of the pointer, in window pixel coordinates. + /// + public int Y + { + get { return y; } + internal set { y = value; } + } + + /// + /// Gets a System.Boolean indicating the state of the specified MouseButton. + /// + /// The MouseButton to check. + /// True if the MouseButton is pressed, false otherwise. + public bool this[MouseButton button] + { + get + { + return IsButtonDown(button); + } + } + + /// + /// Gets a + public ButtonState LeftButton + { + get { return IsButtonDown(MouseButton.Left) ? ButtonState.Pressed : ButtonState.Released; } + } + + /// + /// Gets a + public ButtonState MiddleButton + { + get { return IsButtonDown(MouseButton.Middle) ? ButtonState.Pressed : ButtonState.Released; } + } + + /// + /// Gets a + public ButtonState RightButton + { + get { return IsButtonDown(MouseButton.Right) ? ButtonState.Pressed : ButtonState.Released; } + } + + /// + /// Gets a + public ButtonState XButton1 + { + get { return IsButtonDown(MouseButton.Button1) ? ButtonState.Pressed : ButtonState.Released; } + } + + /// + /// Gets a + public ButtonState XButton2 + { + get { return IsButtonDown(MouseButton.Button2) ? ButtonState.Pressed : ButtonState.Released; } + } + + /// + /// Gets the absolute wheel position in integer units. This property is intended for XNA compatibility. + /// To support high-precision mice, it is recommended to use instead. + /// + public int ScrollWheelValue + { + get { return Wheel; } + } + + /// + /// Checks whether two instances are equal. + /// + /// + /// A instance. + /// + /// + /// A instance. + /// + /// + /// True if both left is equal to right; false otherwise. + /// + public static bool operator ==(MouseState left, MouseState right) + { + return left.Equals(right); + } + + /// + /// Checks whether two instances are not equal. + /// + /// + /// A instance. + /// + /// + /// A instance. + /// + /// + /// True if both left is not equal to right; false otherwise. + /// + public static bool operator !=(MouseState left, MouseState right) + { + return !left.Equals(right); + } + #endregion #region Internal Members @@ -128,6 +270,7 @@ namespace OpenTK.Input for (int i = 0; equal && i < NumInts; i++) equal &= *(b1 + i) == *(b2 + i); } + equal &= X == other.X && Y == other.Y && WheelPrecise == other.WheelPrecise; } return equal; } diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 0510e48d..693d87bb 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -76,6 +76,9 @@ ..\..\Binaries\OpenTK\Release\ + none + 4 + true true @@ -757,6 +760,8 @@ Always + + diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index fd9cb473..b1212377 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -85,8 +85,7 @@ namespace OpenTK.Platform.X11 public virtual OpenTK.Input.IMouseDriver CreateMouseDriver() { - //return new X11Mouse(null); - throw new NotImplementedException(); + return new X11Mouse(null); } #endregion diff --git a/Source/OpenTK/Platform/X11/X11Mouse.cs b/Source/OpenTK/Platform/X11/X11Mouse.cs new file mode 100644 index 00000000..49c8bedc --- /dev/null +++ b/Source/OpenTK/Platform/X11/X11Mouse.cs @@ -0,0 +1,173 @@ + #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 OpenTK.Input; + +namespace OpenTK.Platform.X11 +{ + sealed class X11Mouse : IMouseDriver + { + MouseState mouse = new MouseState(); + X11WindowInfo window; + + // Can either attach itself to the specified window or can hook the root window. + public X11Mouse(X11WindowInfo win) + { + if (win != null) + { + window = win; + } + else + { + using (new XLock(API.DefaultDisplay)) + { + window = new X11WindowInfo(); + window.Display = API.DefaultDisplay; + window.Screen = Functions.XDefaultScreen(window.Display); + window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); + window.WindowHandle = window.RootWindow; + window.EventMask = EventMask.ButtonMotionMask | + EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; + + //Functions.XGrabPointer(window.Display, window.RootWindow, true, + // window.EventMask, GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, IntPtr.Zero, + // IntPtr.Zero, IntPtr.Zero); + //Functions.XSelectInput(window.Display, window.RootWindow, new IntPtr((int)window.EventMask)); + } + } + } + + // Todo: remove this + public IList Mouse { get { throw new NotSupportedException(); } } + + public MouseState GetState() + { + ProcessEvents(); + return mouse; + } + + public MouseState GetState(int index) + { + + // X11Mouse supports a single mouse only + if (index < 0 || index > 1) + throw new ArgumentOutOfRangeException("index"); + + ProcessEvents(); + return mouse; + } + + void WriteBit(MouseButton offset, int enabled) + { + if (enabled != 0) + mouse.EnableBit((int)offset); + else + mouse.DisableBit((int)offset); + } + + void ProcessEvents() + { + IntPtr root, child; + int root_x, root_y, win_x, win_y; + int buttons; + Functions.XQueryPointer(window.Display, window.WindowHandle, out root, out child, + out root_x, out root_y, out win_x, out win_y, out buttons); + mouse.X = root_x; + mouse.Y = root_y; + WriteBit(MouseButton.Left, buttons & (int)MouseMask.Button1Mask); + WriteBit(MouseButton.Middle, buttons & (int)MouseMask.Button2Mask); + WriteBit(MouseButton.Right, buttons & (int)MouseMask.Button3Mask); + if ((buttons & (int)MouseMask.Button4Mask) != 0) + mouse.WheelPrecise++; + if ((buttons & (int)MouseMask.Button5Mask) != 0) + mouse.WheelPrecise--; + WriteBit(MouseButton.Button1, buttons & (int)MouseMask.Button6Mask); + WriteBit(MouseButton.Button2, buttons & (int)MouseMask.Button7Mask); + WriteBit(MouseButton.Button3, buttons & (int)MouseMask.Button8Mask); + +// XEvent e = new XEvent(); +// +// while (true) +// { +// using (new XLock(window.Display)) +// { +// if (!Functions.XCheckWindowEvent(window.Display, window.WindowHandle, window.EventMask, ref e)) +// break; +// +// switch (e.type) +// { +// case XEventName.ButtonPress: +// switch (e.ButtonEvent.button) +// { +// case 1: mouse.EnableBit((int)MouseButton.Left); break; +// case 2: mouse.EnableBit((int)MouseButton.Middle); break; +// case 3: mouse.EnableBit((int)MouseButton.Right); break; +// case 4: mouse.WheelPrecise++; break; +// case 5: mouse.WheelPrecise--; break; +// case 6: mouse.EnableBit((int)MouseButton.Button1); break; +// case 7: mouse.EnableBit((int)MouseButton.Button2); break; +// case 8: mouse.EnableBit((int)MouseButton.Button3); break; +// case 9: mouse.EnableBit((int)MouseButton.Button4); break; +// case 10: mouse.EnableBit((int)MouseButton.Button5); break; +// case 11: mouse.EnableBit((int)MouseButton.Button6); break; +// case 12: mouse.EnableBit((int)MouseButton.Button7); break; +// case 13: mouse.EnableBit((int)MouseButton.Button8); break; +// case 15: mouse.EnableBit((int)MouseButton.Button9); break; +// } +// break; +// +// case XEventName.ButtonRelease: +// switch (e.ButtonEvent.button) +// { +// case 1: mouse.DisableBit((int)MouseButton.Left); break; +// case 2: mouse.DisableBit((int)MouseButton.Middle); break; +// case 3: mouse.DisableBit((int)MouseButton.Right); break; +// case 6: mouse.DisableBit((int)MouseButton.Button1); break; +// case 7: mouse.DisableBit((int)MouseButton.Button2); break; +// case 8: mouse.DisableBit((int)MouseButton.Button3); break; +// case 9: mouse.DisableBit((int)MouseButton.Button4); break; +// case 10: mouse.DisableBit((int)MouseButton.Button5); break; +// case 11: mouse.DisableBit((int)MouseButton.Button6); break; +// case 12: mouse.DisableBit((int)MouseButton.Button7); break; +// case 13: mouse.DisableBit((int)MouseButton.Button8); break; +// case 15: mouse.DisableBit((int)MouseButton.Button9); break; +// } +// break; +// +// case XEventName.MotionNotify: +// mouse.X = e.MotionEvent.x; +// mouse.Y = e.MotionEvent.y; +// break; +// } +// } +// } + } + } +} +