[Platform] Added support for horizontal wheel
authorthefiddler <stapostol@gmail.com>
Sat, 3 May 2014 14:47:03 +0000 (16:47 +0200)
committerthefiddler <stapostol@gmail.com>
Sat, 3 May 2014 14:47:03 +0000 (16:47 +0200)
Source/Examples/OpenTK/Test/GameWindowStates.cs
Source/OpenTK/Input/MouseDevice.cs
Source/OpenTK/Platform/LegacyInputDriver.cs
Source/OpenTK/Platform/NativeWindowBase.cs
Source/OpenTK/Platform/SDL2/Sdl2Mouse.cs
Source/OpenTK/Platform/SDL2/Sdl2NativeWindow.cs
Source/OpenTK/Platform/Windows/API.cs
Source/OpenTK/Platform/Windows/WinGLNative.cs

index 2e5ce40..e75f897 100644 (file)
@@ -26,6 +26,10 @@ namespace Examples.Tests
         bool mouse_in_window = false;
         bool viewport_changed = true;
 
+        // mouse information
+        Vector4 mouse_pos;
+        int mouse_buttons;
+
         // time drift
         Stopwatch watch = new Stopwatch();
         double update_time, render_time;
@@ -57,6 +61,7 @@ namespace Examples.Tests
             MouseLeave += delegate { mouse_in_window = false; };
 
             Mouse.Move += MouseMoveHandler;
+            Mouse.WheelChanged += MouseWheelHandler;
             Mouse.ButtonDown += MouseButtonHandler;
             Mouse.ButtonUp += MouseButtonHandler;
         }
@@ -119,6 +124,10 @@ namespace Examples.Tests
 
         void MouseMoveHandler(object sender, MouseMoveEventArgs e)
         {
+            mouse_pos.X = e.X;
+            mouse_pos.Y = e.Y;
+            mouse_pos.Z = e.Wheel.X;
+            mouse_pos.W = e.Wheel.Y;
         }
 
         void MouseButtonHandler(object sender, MouseButtonEventArgs e)
@@ -127,6 +136,21 @@ namespace Examples.Tests
             {
                 CursorVisible = false;
             }
+
+            if (e.IsPressed)
+            {
+                mouse_buttons |= 1 << (int)e.Button;
+            }
+            else
+            {
+                mouse_buttons &= ~(1 << (int)e.Button);
+            }
+        }
+
+        void MouseWheelHandler(object sender, MouseWheelEventArgs e)
+        {
+            mouse_pos.Z += e.Wheel.Y;
+            mouse_pos.W += e.Wheel.X;
         }
 
         static int Clamp(int val, int min, int max)
@@ -201,6 +225,40 @@ namespace Examples.Tests
             return line;
         }
 
+        int DrawMouseDevice(Graphics gfx, int line)
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.Append("MouseDevice: ");
+            sb.Append(new Vector3(Mouse.X, Mouse.Y, Mouse.Wheel));
+            sb.Append(" ");
+            for (var i = MouseButton.Left; i < MouseButton.LastButton; i++)
+            {
+                if (Mouse[i])
+                {
+                    sb.Append(i);
+                    sb.Append(" ");
+                }
+            }
+            sb.AppendLine();
+            DrawString(gfx, sb.ToString(), line++);
+
+            sb.Remove(0, sb.Length);
+            sb.Append("Mouse events: ");
+            sb.Append(mouse_pos);
+            sb.Append(" ");
+            for (var i = MouseButton.Left; i < MouseButton.LastButton; i++)
+            {
+                if ((mouse_buttons & (1 << (int)i)) != 0)
+                {
+                    sb.Append(i);
+                    sb.Append(" ");
+                }
+            }
+            sb.AppendLine();
+            DrawString(gfx, sb.ToString(), line++);
+            return line;
+        }
+
         static int DrawLegacyJoysticks(Graphics gfx, IList<JoystickDevice> joysticks, int line)
         {
             line++;
@@ -267,7 +325,8 @@ namespace Examples.Tests
                     mouse_in_window ? "inside" : "outside",
                     CursorVisible ? "visible" : "hidden",
                     Focused ? "Focused" : "Not focused"), line++);
-                DrawString(gfx, String.Format("Mouse coordinates: {0}", new Vector3(Mouse.X, Mouse.Y, Mouse.WheelPrecise)), line++);
+
+                line = DrawMouseDevice(gfx, line);
 
                 // Timing information
                 line++;
index 2e922ff..ebcd7f7 100644 (file)
@@ -362,6 +362,24 @@ namespace OpenTK.Input
         #endregion
     }
 
+    /// <summary>
+    /// Represents a mouse wheel.
+    /// </summary>
+    public sealed class MouseWheel
+    {
+        /// <summary>
+        /// Gets the X offset of the wheel.
+        /// </summary>
+        /// <value>The x.</value>
+        public float X { get; internal set; }
+
+        /// <summary>
+        /// Gets the Y offset of the wheel.
+        /// </summary>
+        /// <value>The y.</value>
+        public float Y { get; internal set; }
+    }
+
     #region Event Arguments
 
     /// <summary>
@@ -390,6 +408,7 @@ namespace OpenTK.Input
         /// </summary>
         public MouseEventArgs()
         {
+            Wheel = new MouseWheel();
         }
 
         /// <summary>
@@ -416,7 +435,7 @@ namespace OpenTK.Input
 
         #region Protected Members
 
-        protected internal void SetButton(MouseButton button, ButtonState state)
+        internal void SetButton(MouseButton button, ButtonState state)
         {
             if (button < 0 || button > MouseButton.LastButton)
                 throw new ArgumentOutOfRangeException();
@@ -433,7 +452,7 @@ namespace OpenTK.Input
             }
         }
 
-        protected internal ButtonState GetButton(MouseButton button)
+        internal ButtonState GetButton(MouseButton button)
         {
             if (button < 0 || button > MouseButton.LastButton)
                 throw new ArgumentOutOfRangeException();
@@ -458,21 +477,9 @@ namespace OpenTK.Input
         public int Y { get { return y; } internal set { y = value; } }
 
         /// <summary>
-        /// Gets the offset of the horizontal wheel, if one exists.
-        /// </summary>
-        public float WheelX { get; internal set; }
-
-        /// <summary>
-        /// Gets the offset of the vertical wheel, if one exists.
-        /// </summary>
-        public float WheelY { get; internal set; }
-
-        /// <summary>
-        /// Gets the offset of the vertical wheel, if one exists.
-        /// This is an alias to <see cref="MouseEventArgs.WheelY"/>
+        /// Gets the status of the mouse wheel.
         /// </summary>
-        /// <value>The wheel.</value>
-        public float Wheel { get { return WheelY; } internal set { WheelY = value; } }
+        public MouseWheel Wheel { get; private set; }
 
         /// <summary>
         /// Gets the <see cref="ButtonState"/> of the left mouse button.
@@ -705,7 +712,7 @@ namespace OpenTK.Input
         public MouseWheelEventArgs(int x, int y, int value, int delta)
             : base(x, y)
         {
-            WheelY = value;
+            Wheel.Y = value;
             this.delta = delta;
         }
 
@@ -726,7 +733,7 @@ namespace OpenTK.Input
         /// Gets the value of the wheel in integer units.
         /// To support high-precision mice, it is recommended to use <see cref="ValuePrecise"/> instead.
         /// </summary>
-        public int Value { get { return (int)Math.Round(WheelY, MidpointRounding.AwayFromZero); } }
+        public int Value { get { return (int)Math.Round(Wheel.Y, MidpointRounding.AwayFromZero); } }
 
         /// <summary>
         /// Gets the change in value of the wheel for this event in integer units.
@@ -737,7 +744,7 @@ namespace OpenTK.Input
         /// <summary>
         /// Gets the precise value of the wheel in floating-point units.
         /// </summary>
-        public float ValuePrecise { get { return WheelY; } internal set { WheelY = value; } }
+        public float ValuePrecise { get { return Wheel.Y; } internal set { Wheel.Y = value; } }
 
         /// <summary>
         /// Gets the precise change in value of the wheel for this event in floating-point units.
index 290f632..96d0a02 100644 (file)
@@ -78,7 +78,7 @@ namespace OpenTK.Platform
 
             window.MouseWheel += (sender, e) =>
             {
-                mouse.WheelPrecise = e.WheelY;
+                mouse.WheelPrecise = e.Wheel.Y;
             };
 
             // Hook keyboard events
index ed7f32e..64e6bee 100644 (file)
@@ -49,6 +49,10 @@ namespace OpenTK.Platform
         readonly protected KeyboardKeyEventArgs KeyUpArgs = new KeyboardKeyEventArgs();
         readonly protected KeyPressEventArgs KeyPressArgs = new KeyPressEventArgs((char)0);
 
+        // In order to simplify mouse event implementation,
+        // we can store the current mouse state here.
+        protected MouseState MouseState = new MouseState();
+
         internal NativeWindowBase()
         {
             LegacyInputDriver = new LegacyInputDriver(this);
index ffd8cc3..887ad7a 100644 (file)
@@ -33,28 +33,18 @@ using OpenTK.Input;
 
 namespace OpenTK.Platform.SDL2
 {
-    class Sdl2Mouse : IMouseDriver2, IMouseDriver
+    class Sdl2Mouse : IMouseDriver2
     {
         MouseState state;
 
-        readonly List<MouseDevice> mice =
-            new List<MouseDevice>();
-        readonly IList<MouseDevice> mice_readonly;
-
         public Sdl2Mouse()
         {
             state.IsConnected = true;
-
-            mice.Add(new MouseDevice());
-            mice[0].Description = "Standard mouse";
-            mice[0].NumberOfButtons = 3;
-            mice[0].NumberOfWheels = 1;
-            mice_readonly = mice.AsReadOnly();
         }
 
         #region Private Members
 
-        MouseButton TranslateButton(Button button)
+        static internal MouseButton TranslateButton(Button button)
         {
             switch (button)
             {
@@ -98,33 +88,18 @@ namespace OpenTK.Platform.SDL2
         public void ProcessWheelEvent(MouseWheelEvent wheel)
         {
             state.WheelPrecise += wheel.Y;
-            mice[0].WheelPrecise += wheel.Y;
         }
 
         public void ProcessMouseEvent(MouseMotionEvent motion)
         {
             state.X += motion.Xrel;
             state.Y += motion.Yrel;
-            mice[0].Position = new Point(motion.X, motion.Y);
         }
 
         public void ProcessMouseEvent(MouseButtonEvent button)
         {
             bool pressed = button.State == State.Pressed;
             SetButtonState(TranslateButton(button.Button), pressed);
-            mice[0][TranslateButton(button.Button)] = pressed;
-        }
-
-        #endregion
-
-        #region IMouseDriver Members
-
-        public IList<MouseDevice> Mouse
-        {
-            get
-            {
-                return mice_readonly;
-            }
         }
 
         #endregion
index f30ba51..8c3367f 100644 (file)
@@ -175,7 +175,7 @@ namespace OpenTK.Platform.SDL2
                     case EventType.MOUSEBUTTONUP:
                         if (windows.TryGetValue(ev.Button.WindowID, out window))
                         {
-                            ProcessButtonEvent(window, ev);
+                            ProcessMouseButtonEvent(window, ev.Button);
                             processed = true;
                         }
                         break;
@@ -183,7 +183,7 @@ namespace OpenTK.Platform.SDL2
                     case EventType.MOUSEMOTION:
                         if (windows.TryGetValue(ev.Motion.WindowID, out window))
                         {
-                            ProcessMotionEvent(window, ev);
+                            ProcessMouseMotionEvent(window, ev.Motion);
                             processed = true;
                         }
                         break;
@@ -191,7 +191,7 @@ namespace OpenTK.Platform.SDL2
                     case EventType.MOUSEWHEEL:
                         if (windows.TryGetValue(ev.Wheel.WindowID, out window))
                         {
-                            ProcessWheelEvent(window, ev);
+                            ProcessMouseWheelEvent(window, ev.Wheel);
                             processed = true;
                         }
                         break;
@@ -209,9 +209,9 @@ namespace OpenTK.Platform.SDL2
             return processed ? 0 : 1;
         }
 
-        static void ProcessButtonEvent(Sdl2NativeWindow window, Event ev)
+        static void ProcessMouseButtonEvent(Sdl2NativeWindow window, MouseButtonEvent ev)
         {
-            bool button_pressed = ev.Button.State == State.Pressed;
+            bool button_pressed = ev.State == State.Pressed;
 
             // We need MouseUp events to be reported even if they occur
             // outside the window. SetWindowGrab ensures we get them.
@@ -220,6 +220,23 @@ namespace OpenTK.Platform.SDL2
                 SDL.SetWindowGrab(window.window.Handle,
                     button_pressed ? true : false);
             }
+
+            var e = button_pressed ? window.MouseDownArgs : window.MouseUpArgs;
+            e.Button = Sdl2Mouse.TranslateButton(ev.Button);
+            e.IsPressed = button_pressed;
+            e.X = ev.X;
+            e.Y = ev.Y;
+            e.Wheel.X = window.MouseWheelArgs.Wheel.X;
+            e.Wheel.Y = window.MouseWheelArgs.Wheel.Y;
+
+            if (button_pressed)
+            {
+                window.OnMouseDown(e);
+            }
+            else
+            {
+                window.OnMouseUp(e);
+            }
         }
 
         static void ProcessKeyEvent(Sdl2NativeWindow window, Event ev)
@@ -273,16 +290,32 @@ namespace OpenTK.Platform.SDL2
             }
         }
 
-        static void ProcessMotionEvent(Sdl2NativeWindow window, Event ev)
+        static void ProcessMouseMotionEvent(Sdl2NativeWindow window, MouseMotionEvent ev)
+        {
+            //float scale = window.ClientSize.Width / (float)window.Size.Width;
+            var e = window.MouseMoveArgs;
+            e.X = ev.X;
+            e.Y = ev.Y;
+            SetMouseButtons(e, ev.State);
+            window.OnMouseMove(e);
+        }
+
+        static void SetMouseButtons(MouseEventArgs e, ButtonFlags buttons)
         {
-            float scale = window.ClientSize.Width / (float)window.Size.Width;
-            //window.mouse.Position = new Point(
-            //    (int)(ev.motion.x * scale), (int)(ev.motion.y * scale));
+            for (int i = 0; i < 5; i++)
+            {
+                // Note: OpenTK MouseButton is identical to SDL2 Button
+                bool pressed = ((int)buttons & (1 << i)) != 0;
+                e.SetButton((MouseButton)i, pressed ? ButtonState.Pressed : ButtonState.Released);
+            }
         }
 
-        static void ProcessWheelEvent(Sdl2NativeWindow window, Event ev)
+        static void ProcessMouseWheelEvent(Sdl2NativeWindow window, MouseWheelEvent ev)
         {
-            //window.mouse.Wheel += ev.wheel.y;
+            var e = window.MouseWheelArgs;
+            e.Wheel.Y = ev.Y;
+            e.Wheel.X = ev.X;
+            window.OnMouseWheel(e);
         }
 
         static void ProcessWindowEvent(Sdl2NativeWindow window, WindowEvent e)
index 454d2aa..3a0fd54 100644 (file)
@@ -4197,7 +4197,6 @@ namespace OpenTK.Platform.Windows
         MBUTTONUP = 0x0208,
         MBUTTONDBLCLK = 0x0209,
         MOUSEWHEEL = 0x020A,
-        MOUSELAST = 0x020D,
         /// <summary>
         /// Windows 2000 and higher only.
         /// </summary>
@@ -4210,6 +4209,10 @@ namespace OpenTK.Platform.Windows
         /// Windows 2000 and higher only.
         /// </summary>
         XBUTTONDBLCLK    = 0x020D,
+        /// <summary>
+        /// Windows Vista and higher only.
+        /// </summary>
+        MOUSEHWHEEL = 0x020E,
         PARENTNOTIFY = 0x0210,
         ENTERMENULOOP = 0x0211,
         EXITMENULOOP = 0x0212,
index 4e8f732..da56089 100644 (file)
@@ -506,7 +506,15 @@ namespace OpenTK.Platform.Windows
         {
             // This is due to inconsistent behavior of the WParam value on 64bit arch, whese
             // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
-            MouseWheelArgs.Wheel += ((long)wParam << 32 >> 48) / 120.0f;
+            MouseWheelArgs.Wheel.Y += ((long)wParam << 32 >> 48) / 120.0f;
+            OnMouseWheel(MouseWheelArgs);
+        }
+
+        void HandleMouseHWheel(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
+        {
+            // This is due to inconsistent behavior of the WParam value on 64bit arch, whese
+            // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
+            MouseWheelArgs.Wheel.X += ((long)wParam << 32 >> 48) / 120.0f;
             OnMouseWheel(MouseWheelArgs);
         }
 
@@ -729,6 +737,10 @@ namespace OpenTK.Platform.Windows
                     HandleMouseWheel(handle, message, wParam, lParam);
                     break;
 
+                case WindowMessage.MOUSEHWHEEL:
+                    HandleMouseHWheel(handle, message, wParam, lParam);
+                    break;
+
                 case WindowMessage.LBUTTONDOWN:
                     HandleLButtonDown(handle, message, wParam, lParam);
                     break;