{
mouse_pos.X = e.X;
mouse_pos.Y = e.Y;
- mouse_pos.Z = e.Wheel.X;
- mouse_pos.W = e.Wheel.Y;
+ mouse_pos.Z = e.Mouse.Scroll.X;
+ mouse_pos.W = e.Mouse.Scroll.Y;
}
void MouseButtonHandler(object sender, MouseButtonEventArgs e)
void MouseWheelHandler(object sender, MouseWheelEventArgs e)
{
- mouse_pos.Z += e.Wheel.Y;
- mouse_pos.W += e.Wheel.X;
+ mouse_pos.Z += e.Mouse.Scroll.Y;
+ mouse_pos.W += e.Mouse.Scroll.X;
}
static int Clamp(int val, int min, int max)
#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>
- /// Defines the event data for <see cref="MouseDevice"/> events.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Do not cache instances of this type outside their event handler.
- /// If necessary, you can clone an instance using the
- /// <see cref="MouseEventArgs(MouseEventArgs)"/> constructor.
- /// </para>
- /// </remarks>
- public class MouseEventArgs : EventArgs
- {
- #region Fields
-
- int x, y;
- int buttons;
-
- #endregion
-
- #region Constructors
-
- /// <summary>
- /// Constructs a new instance.
- /// </summary>
- public MouseEventArgs()
- {
- Wheel = new MouseWheel();
- }
-
- /// <summary>
- /// Constructs a new instance.
- /// </summary>
- /// <param name="x">The X position.</param>
- /// <param name="y">The Y position.</param>
- public MouseEventArgs(int x, int y)
- {
- this.x = x;
- this.y = y;
- }
-
- /// <summary>
- /// Constructs a new instance.
- /// </summary>
- /// <param name="args">The <see cref="MouseEventArgs"/> instance to clone.</param>
- public MouseEventArgs(MouseEventArgs args)
- : this(args.x, args.y)
- {
- }
-
- #endregion
-
- #region Protected Members
-
- internal void SetButton(MouseButton button, ButtonState state)
- {
- if (button < 0 || button > MouseButton.LastButton)
- throw new ArgumentOutOfRangeException();
-
- switch (state)
- {
- case ButtonState.Pressed:
- buttons |= 1 << (int)button;
- break;
-
- case ButtonState.Released:
- buttons &= ~(1 << (int)button);
- break;
- }
- }
-
- internal ButtonState GetButton(MouseButton button)
- {
- if (button < 0 || button > MouseButton.LastButton)
- throw new ArgumentOutOfRangeException();
-
- return
- (buttons & (1 << (int)button)) != 0 ?
- ButtonState.Pressed : ButtonState.Released;
- }
-
- #endregion
-
- #region Public Members
-
- /// <summary>
- /// Gets the X position of the mouse for the event.
- /// </summary>
- public int X { get { return x; } internal set { x = value; } }
-
- /// <summary>
- /// Gets the Y position of the mouse for the event.
- /// </summary>
- public int Y { get { return y; } internal set { y = value; } }
-
- /// <summary>
- /// Gets the status of the mouse wheel.
- /// </summary>
- public MouseWheel Wheel { get; private set; }
-
- /// <summary>
- /// Gets the <see cref="ButtonState"/> of the left mouse button.
- /// </summary>
- public ButtonState LeftButton
- {
- get { return GetButton(MouseButton.Left); }
- internal set { SetButton(MouseButton.Left, value); }
- }
-
- /// <summary>
- /// Gets the <see cref="ButtonState"/> of the right mouse button.
- /// </summary>
- public ButtonState RightButton
- {
- get { return GetButton(MouseButton.Right); }
- internal set { SetButton(MouseButton.Right, value); }
- }
-
- /// <summary>
- /// Gets the <see cref="ButtonState"/> of the middle mouse button.
- /// </summary>
- public ButtonState MiddleButton
- {
- get { return GetButton(MouseButton.Middle); }
- internal set { SetButton(MouseButton.Middle, value); }
- }
-
- /// <summary>
- /// Gets the <see cref="ButtonState"/> of the first extra mouse button.
- /// </summary>
- public ButtonState X1Button
- {
- get { return GetButton(MouseButton.Button1); }
- internal set { SetButton(MouseButton.Button1, value); }
- }
-
- /// <summary>
- /// Gets the <see cref="ButtonState"/> of the second extra mouse button.
- /// </summary>
- public ButtonState X2Button
- {
- get { return GetButton(MouseButton.Button2); }
- internal set { SetButton(MouseButton.Button2, value); }
- }
-
- /// <summary>
- /// Gets a <see cref="System.Drawing.Point"/> representing the location of the mouse for the event.
- /// </summary>
- public Point Position
- {
- get { return new Point(x, y); }
- set
- {
- X = value.X;
- Y = value.Y;
- }
- }
-
- #endregion
- }
-
- /// <summary>
- /// Defines the event data for <see cref="MouseDevice.Move"/> events.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Do not cache instances of this type outside their event handler.
- /// If necessary, you can clone an instance using the
- /// <see cref="MouseMoveEventArgs(MouseMoveEventArgs)"/> constructor.
- /// </para>
- /// </remarks>
- public class MouseMoveEventArgs : MouseEventArgs
- {
- #region Fields
-
- int x_delta, y_delta;
-
- #endregion
-
- #region Constructors
-
- /// <summary>
- /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
- /// </summary>
- public MouseMoveEventArgs() { }
-
- /// <summary>
- /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
- /// </summary>
- /// <param name="x">The X position.</param>
- /// <param name="y">The Y position.</param>
- /// <param name="xDelta">The change in X position produced by this event.</param>
- /// <param name="yDelta">The change in Y position produced by this event.</param>
- public MouseMoveEventArgs(int x, int y, int xDelta, int yDelta)
- : base(x, y)
- {
- XDelta = xDelta;
- YDelta = yDelta;
- }
-
- /// <summary>
- /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
- /// </summary>
- /// <param name="args">The <see cref="MouseMoveEventArgs"/> instance to clone.</param>
- public MouseMoveEventArgs(MouseMoveEventArgs args)
- : this(args.X, args.Y, args.XDelta, args.YDelta)
- {
- }
-
- #endregion
-
- #region Public Members
-
- /// <summary>
- /// Gets the change in X position produced by this event.
- /// </summary>
- public int XDelta { get { return x_delta; } internal set { x_delta = value; } }
-
- /// <summary>
- /// Gets the change in Y position produced by this event.
- /// </summary>
- public int YDelta { get { return y_delta; } internal set { y_delta = value; } }
-
- #endregion
- }
-
- /// <summary>
- /// Defines the event data for <see cref="MouseDevice.ButtonDown"/> and <see cref="MouseDevice.ButtonUp"/> events.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Do not cache instances of this type outside their event handler.
- /// If necessary, you can clone an instance using the
- /// <see cref="MouseButtonEventArgs(MouseButtonEventArgs)"/> constructor.
- /// </para>
- /// </remarks>
- public class MouseButtonEventArgs : MouseEventArgs
- {
- #region Fields
-
- MouseButton button;
- bool pressed;
-
- #endregion
-
- #region Constructors
-
- /// <summary>
- /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
- /// </summary>
- public MouseButtonEventArgs() { }
-
- /// <summary>
- /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
- /// </summary>
- /// <param name="x">The X position.</param>
- /// <param name="y">The Y position.</param>
- /// <param name="button">The mouse button for the event.</param>
- /// <param name="pressed">The current state of the button.</param>
- public MouseButtonEventArgs(int x, int y, MouseButton button, bool pressed)
- : base(x, y)
- {
- this.button = button;
- this.pressed = pressed;
- }
-
- /// <summary>
- /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
- /// </summary>
- /// <param name="args">The <see cref="MouseButtonEventArgs"/> instance to clone.</param>
- public MouseButtonEventArgs(MouseButtonEventArgs args)
- : this(args.X, args.Y, args.Button, args.IsPressed)
- {
- }
-
- #endregion
-
- #region Public Members
-
- /// <summary>
- /// Gets the <see cref="MouseButton"/> that triggered this event.
- /// </summary>
- public MouseButton Button { get { return button; } internal set { button = value; } }
-
- /// <summary>
- /// Gets a System.Boolean representing the state of the mouse button for the event.
- /// </summary>
- public bool IsPressed
- {
- get { return GetButton(Button) == ButtonState.Pressed; }
- internal set { SetButton(Button, value ? ButtonState.Pressed : ButtonState.Released); }
- }
-
- #endregion
- }
-
- /// <summary>
- /// Defines the event data for <see cref="MouseDevice.WheelChanged"/> events.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Do not cache instances of this type outside their event handler.
- /// If necessary, you can clone an instance using the
- /// <see cref="MouseWheelEventArgs(MouseWheelEventArgs)"/> constructor.
- /// </para>
- /// </remarks>
- public class MouseWheelEventArgs : MouseEventArgs
- {
- #region Fields
-
- float delta;
-
- #endregion
-
- #region Constructors
-
- /// <summary>
- /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
- /// </summary>
- public MouseWheelEventArgs() { }
-
- /// <summary>
- /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
- /// </summary>
- /// <param name="x">The X position.</param>
- /// <param name="y">The Y position.</param>
- /// <param name="value">The value of the wheel.</param>
- /// <param name="delta">The change in value of the wheel for this event.</param>
- public MouseWheelEventArgs(int x, int y, int value, int delta)
- : base(x, y)
- {
- Wheel.Y = value;
- this.delta = delta;
- }
-
- /// <summary>
- /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
- /// </summary>
- /// <param name="args">The <see cref="MouseWheelEventArgs"/> instance to clone.</param>
- public MouseWheelEventArgs(MouseWheelEventArgs args)
- : this(args.X, args.Y, args.Value, args.Delta)
- {
- }
-
- #endregion
-
- #region Public Members
-
- /// <summary>
- /// 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(Wheel.Y, MidpointRounding.AwayFromZero); } }
-
- /// <summary>
- /// Gets the change in value of the wheel for this event in integer units.
- /// To support high-precision mice, it is recommended to use <see cref="DeltaPrecise"/> instead.
- /// </summary>
- public int Delta { get { return (int)Math.Round(delta, MidpointRounding.AwayFromZero); } }
-
- /// <summary>
- /// Gets the precise value of the wheel in floating-point units.
- /// </summary>
- 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.
- /// </summary>
- public float DeltaPrecise { get { return delta; } internal set { delta = value; } }
-
- #endregion
- }
-
- #endregion
}
--- /dev/null
+#region License
+//
+// MouseEventArgs.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// 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.Drawing;
+
+namespace OpenTK.Input
+{
+ /// <summary>
+ /// Defines the event data for <see cref="MouseDevice"/> events.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Do not cache instances of this type outside their event handler.
+ /// If necessary, you can clone an instance using the
+ /// <see cref="MouseEventArgs(MouseEventArgs)"/> constructor.
+ /// </para>
+ /// </remarks>
+ public class MouseEventArgs : EventArgs
+ {
+ #region Fields
+
+ MouseState state;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructs a new instance.
+ /// </summary>
+ public MouseEventArgs()
+ {
+ state.SetIsConnected(true);
+ }
+
+ /// <summary>
+ /// Constructs a new instance.
+ /// </summary>
+ /// <param name="x">The X position.</param>
+ /// <param name="y">The Y position.</param>
+ public MouseEventArgs(int x, int y)
+ : this()
+ {
+ state.X = x;
+ state.Y = y;
+ }
+
+ /// <summary>
+ /// Constructs a new instance.
+ /// </summary>
+ /// <param name="args">The <see cref="MouseEventArgs"/> instance to clone.</param>
+ public MouseEventArgs(MouseEventArgs args)
+ : this(args.X, args.Y)
+ {
+ }
+
+ #endregion
+
+ #region Protected Members
+
+ internal void SetButton(MouseButton button, ButtonState state)
+ {
+ if (button < 0 || button > MouseButton.LastButton)
+ throw new ArgumentOutOfRangeException();
+
+ switch (state)
+ {
+ case ButtonState.Pressed:
+ this.state.EnableBit((int)button);
+ break;
+
+ case ButtonState.Released:
+ this.state.DisableBit((int)button);
+ break;
+ }
+ }
+
+ internal ButtonState GetButton(MouseButton button)
+ {
+ if (button < 0 || button > MouseButton.LastButton)
+ throw new ArgumentOutOfRangeException();
+
+ return
+ state.ReadBit((int)button) ?
+ ButtonState.Pressed : ButtonState.Released;
+ }
+
+ #endregion
+
+ #region Public Members
+
+ /// <summary>
+ /// Gets the X position of the mouse for the event.
+ /// </summary>
+ public int X { get { return state.X; } internal set { state.X = value; } }
+
+ /// <summary>
+ /// Gets the Y position of the mouse for the event.
+ /// </summary>
+ public int Y { get { return state.Y; } internal set { state.Y = value; } }
+
+ /// <summary>
+ /// Gets a <see cref="System.Drawing.Point"/> representing the location of the mouse for the event.
+ /// </summary>
+ public Point Position
+ {
+ get { return new Point(state.X, state.Y); }
+ set
+ {
+ X = value.X;
+ Y = value.Y;
+ }
+ }
+
+ /// <summary>
+ /// Gets the current <see cref="OpenTK.Input.MouseState"/>.
+ /// </summary>
+ public MouseState Mouse
+ {
+ get { return state; }
+ internal set { state = value; }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Defines the event data for <see cref="MouseDevice.Move"/> events.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Do not cache instances of this type outside their event handler.
+ /// If necessary, you can clone an instance using the
+ /// <see cref="MouseMoveEventArgs(MouseMoveEventArgs)"/> constructor.
+ /// </para>
+ /// </remarks>
+ public class MouseMoveEventArgs : MouseEventArgs
+ {
+ #region Fields
+
+ int x_delta, y_delta;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
+ /// </summary>
+ public MouseMoveEventArgs() { }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
+ /// </summary>
+ /// <param name="x">The X position.</param>
+ /// <param name="y">The Y position.</param>
+ /// <param name="xDelta">The change in X position produced by this event.</param>
+ /// <param name="yDelta">The change in Y position produced by this event.</param>
+ public MouseMoveEventArgs(int x, int y, int xDelta, int yDelta)
+ : base(x, y)
+ {
+ XDelta = xDelta;
+ YDelta = yDelta;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseMoveEventArgs"/> instance.
+ /// </summary>
+ /// <param name="args">The <see cref="MouseMoveEventArgs"/> instance to clone.</param>
+ public MouseMoveEventArgs(MouseMoveEventArgs args)
+ : this(args.X, args.Y, args.XDelta, args.YDelta)
+ {
+ }
+
+ #endregion
+
+ #region Public Members
+
+ /// <summary>
+ /// Gets the change in X position produced by this event.
+ /// </summary>
+ public int XDelta { get { return x_delta; } internal set { x_delta = value; } }
+
+ /// <summary>
+ /// Gets the change in Y position produced by this event.
+ /// </summary>
+ public int YDelta { get { return y_delta; } internal set { y_delta = value; } }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Defines the event data for <see cref="MouseDevice.ButtonDown"/> and <see cref="MouseDevice.ButtonUp"/> events.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Do not cache instances of this type outside their event handler.
+ /// If necessary, you can clone an instance using the
+ /// <see cref="MouseButtonEventArgs(MouseButtonEventArgs)"/> constructor.
+ /// </para>
+ /// </remarks>
+ public class MouseButtonEventArgs : MouseEventArgs
+ {
+ #region Fields
+
+ MouseButton button;
+ bool pressed;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
+ /// </summary>
+ public MouseButtonEventArgs() { }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
+ /// </summary>
+ /// <param name="x">The X position.</param>
+ /// <param name="y">The Y position.</param>
+ /// <param name="button">The mouse button for the event.</param>
+ /// <param name="pressed">The current state of the button.</param>
+ public MouseButtonEventArgs(int x, int y, MouseButton button, bool pressed)
+ : base(x, y)
+ {
+ this.button = button;
+ this.pressed = pressed;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseButtonEventArgs"/> instance.
+ /// </summary>
+ /// <param name="args">The <see cref="MouseButtonEventArgs"/> instance to clone.</param>
+ public MouseButtonEventArgs(MouseButtonEventArgs args)
+ : this(args.X, args.Y, args.Button, args.IsPressed)
+ {
+ }
+
+ #endregion
+
+ #region Public Members
+
+ /// <summary>
+ /// Gets the <see cref="MouseButton"/> that triggered this event.
+ /// </summary>
+ public MouseButton Button { get { return button; } internal set { button = value; } }
+
+ /// <summary>
+ /// Gets a System.Boolean representing the state of the mouse button for the event.
+ /// </summary>
+ public bool IsPressed
+ {
+ get { return GetButton(Button) == ButtonState.Pressed; }
+ internal set { SetButton(Button, value ? ButtonState.Pressed : ButtonState.Released); }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Defines the event data for <see cref="MouseDevice.WheelChanged"/> events.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Do not cache instances of this type outside their event handler.
+ /// If necessary, you can clone an instance using the
+ /// <see cref="MouseWheelEventArgs(MouseWheelEventArgs)"/> constructor.
+ /// </para>
+ /// </remarks>
+ public class MouseWheelEventArgs : MouseEventArgs
+ {
+ #region Fields
+
+ float delta;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
+ /// </summary>
+ public MouseWheelEventArgs() { }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
+ /// </summary>
+ /// <param name="x">The X position.</param>
+ /// <param name="y">The Y position.</param>
+ /// <param name="value">The value of the wheel.</param>
+ /// <param name="delta">The change in value of the wheel for this event.</param>
+ public MouseWheelEventArgs(int x, int y, int value, int delta)
+ : base(x, y)
+ {
+ Mouse.SetScrollAbsolute(Mouse.Scroll.X, value);
+ this.delta = delta;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="MouseWheelEventArgs"/> instance.
+ /// </summary>
+ /// <param name="args">The <see cref="MouseWheelEventArgs"/> instance to clone.</param>
+ public MouseWheelEventArgs(MouseWheelEventArgs args)
+ : this(args.X, args.Y, args.Value, args.Delta)
+ {
+ }
+
+ #endregion
+
+ #region Public Members
+
+ /// <summary>
+ /// 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(Mouse.Scroll.Y, MidpointRounding.AwayFromZero); } }
+
+ /// <summary>
+ /// Gets the change in value of the wheel for this event in integer units.
+ /// To support high-precision mice, it is recommended to use <see cref="DeltaPrecise"/> instead.
+ /// </summary>
+ public int Delta { get { return (int)Math.Round(delta, MidpointRounding.AwayFromZero); } }
+
+ /// <summary>
+ /// Gets the precise value of the wheel in floating-point units.
+ /// </summary>
+ public float ValuePrecise
+ {
+ get { return Mouse.Scroll.Y; }
+ internal set { Mouse.SetScrollAbsolute(Mouse.Scroll.X, value); }
+ }
+
+ /// <summary>
+ /// Gets the precise change in value of the wheel for this event in floating-point units.
+ /// </summary>
+ public float DeltaPrecise { get { return delta; } internal set { delta = value; } }
+
+ #endregion
+ }
+}
+
--- /dev/null
+#region License
+//
+// MouseWheel.cs
+//
+// Author:
+// Stefanos A. <stapostol@gmail.com>
+//
+// 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;
+
+namespace OpenTK.Input
+{
+ /// <summary>
+ /// Represents the state of a mouse wheel.
+ /// </summary>
+ public struct MouseScrollWheel : IEquatable<MouseScrollWheel>
+ {
+ #region Public Members
+
+ /// <summary>
+ /// Gets the absolute horizontal offset of the wheel,
+ /// or 0 if no horizontal scroll wheel exists.
+ /// </summary>
+ /// <value>The x.</value>
+ public float X { get; internal set; }
+
+ /// <summary>
+ /// Gets the absolute vertical offset of the wheel,
+ /// or 0 if no vertical scroll wheel exists.
+ /// </summary>
+ /// <value>The y.</value>
+ public float Y { get; internal set; }
+
+ /// <param name="left">A <see cref="MouseScrollWheel"/> instance to test for equality.</param>
+ /// <param name="right">A <see cref="MouseScrollWheel"/> instance to test for equality.</param>
+ public static bool operator ==(MouseScrollWheel left, MouseScrollWheel right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <param name="left">A <see cref="MouseScrollWheel"/> instance to test for inequality.</param>
+ /// <param name="right">A <see cref="MouseScrollWheel"/> instance to test for inequality.</param>
+ public static bool operator !=(MouseScrollWheel left, MouseScrollWheel right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String"/> that represents the current <see cref="OpenTK.Input.MouseScrollWheel"/>.
+ /// </summary>
+ /// <returns>A <see cref="System.String"/> that represents the current <see cref="OpenTK.Input.MouseScrollWheel"/>.</returns>
+ public override string ToString()
+ {
+ return string.Format("[MouseScrollWheel: X={0}, Y={1}]", X, Y);
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a <see cref="OpenTK.Input.MouseScrollWheel"/> object.
+ /// </summary>
+ /// <returns>A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a
+ /// hash table.</returns>
+ public override int GetHashCode()
+ {
+ return X.GetHashCode() ^ Y.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="OpenTK.Input.MouseScrollWheel"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="OpenTK.Input.MouseScrollWheel"/>.</param>
+ /// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current
+ /// <see cref="OpenTK.Input.MouseScrollWheel"/>; otherwise, <c>false</c>.</returns>
+ public override bool Equals(object obj)
+ {
+ return
+ obj is MouseScrollWheel &&
+ Equals((MouseScrollWheel)obj);
+ }
+
+ #endregion
+
+ #region IEquatable Members
+
+ /// <summary>
+ /// Determines whether the specified <see cref="OpenTK.Input.MouseScrollWheel"/> is equal to the current <see cref="OpenTK.Input.MouseScrollWheel"/>.
+ /// </summary>
+ /// <param name="other">The <see cref="OpenTK.Input.MouseScrollWheel"/> to compare with the current <see cref="OpenTK.Input.MouseScrollWheel"/>.</param>
+ /// <returns><c>true</c> if the specified <see cref="OpenTK.Input.MouseScrollWheel"/> is equal to the current
+ /// <see cref="OpenTK.Input.MouseScrollWheel"/>; otherwise, <c>false</c>.</returns>
+ public bool Equals(MouseScrollWheel other)
+ {
+ return X == other.X && Y == other.Y;
+ }
+
+ #endregion
+ }
+}
+
{
#region Fields
- // Allocate enough ints to store all mouse buttons
- const int IntSize = sizeof(int);
- const int NumInts = ((int)MouseButton.LastButton + IntSize - 1) / IntSize;
- // The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
- unsafe fixed int Buttons[NumInts];
int x, y;
- float wheel;
+ MouseScrollWheel scroll;
+ ushort buttons;
bool is_connected;
#endregion
/// </summary>
public int Wheel
{
- get { return (int)Math.Round(wheel, MidpointRounding.AwayFromZero); }
+ get { return (int)Math.Round(scroll.Y, MidpointRounding.AwayFromZero); }
}
/// <summary>
/// </summary>
public float WheelPrecise
{
- get { return wheel; }
- internal set
- {
- wheel = value;
- }
+ get { return scroll.Y; }
+ }
+
+ /// <summary>
+ /// Gets a <see cref="OpenTK.Input.MouseScrollWheel"/> instance,
+ /// representing the current state of the mouse scroll wheel.
+ /// </summary>
+ public MouseScrollWheel Scroll
+ {
+ get { return scroll; }
}
/// <summary>
/// </returns>
public override int GetHashCode()
{
- unsafe
- {
- fixed (int* b = Buttons)
- {
- return b->GetHashCode() ^ X.GetHashCode() ^ Y.GetHashCode() ^ WheelPrecise.GetHashCode();
- }
- }
+ return buttons.GetHashCode() ^ X.GetHashCode() ^ Y.GetHashCode() ^ scroll.GetHashCode();
}
#endregion
internal bool ReadBit(int offset)
{
ValidateOffset(offset);
-
- int int_offset = offset / 32;
- int bit_offset = offset % 32;
- unsafe
- {
- fixed (int* b = Buttons)
- {
- return (*(b + int_offset) & (1 << bit_offset)) != 0u;
- }
- }
+ return (buttons & (1 << offset)) != 0;
}
internal void EnableBit(int offset)
{
ValidateOffset(offset);
-
- int int_offset = offset / 32;
- int bit_offset = offset % 32;
- unsafe
- {
- fixed (int* b = Buttons)
- {
- *(b + int_offset) |= 1 << bit_offset;
- }
- }
+ buttons |= unchecked((ushort)(1 << offset));
}
internal void DisableBit(int offset)
{
ValidateOffset(offset);
-
- int int_offset = offset / 32;
- int bit_offset = offset % 32;
- unsafe
- {
- fixed (int* b = Buttons)
- {
- *(b + int_offset) &= ~(1 << bit_offset);
- }
- }
+ buttons &= unchecked((ushort)(~(1 << offset)));
}
internal void MergeBits(MouseState other)
{
unsafe
{
- int* b2 = other.Buttons;
- fixed (int* b1 = Buttons)
- {
- for (int i = 0; i < NumInts; i++)
- *(b1 + i) |= *(b2 + i);
- }
-
- WheelPrecise += other.WheelPrecise;
+ buttons |= other.buttons;
+ SetScrollRelative(other.scroll.X, other.scroll.Y);
X += other.X;
Y += other.Y;
IsConnected |= other.IsConnected;
IsConnected = value;
}
+ #region Internal Members
+
+ internal void SetScrollAbsolute(float x, float y)
+ {
+ scroll.X = x;
+ scroll.Y = y;
+ }
+
+ internal void SetScrollRelative(float x, float y)
+ {
+ scroll.X += x;
+ scroll.Y += y;
+ }
+
+ #endregion
+
#endregion
#region Private Members
static void ValidateOffset(int offset)
{
- if (offset < 0 || offset >= NumInts * IntSize)
+ if (offset < 0 || offset >= 16)
throw new ArgumentOutOfRangeException("offset");
}
/// <returns>True, if both instances are equal; false otherwise.</returns>
public bool Equals(MouseState other)
{
- bool equal = true;
- unsafe
- {
- int* b2 = other.Buttons;
- fixed (int* b1 = Buttons)
- {
- 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;
+ return
+ buttons == other.buttons &&
+ X == other.X &&
+ Y == other.Y &&
+ Scroll == other.Scroll;
}
#endregion
<Compile Include="WindowIcon.cs" />
<Compile Include="Platform\MacOS\Cocoa\NSBitmapFormat.cs" />
<Compile Include="Platform\NativeWindowBase.cs" />
+ <Compile Include="Input\MouseScrollWheel.cs" />
+ <Compile Include="Input\MouseEventArgs.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
window.MouseWheel += (sender, e) =>
{
- mouse.WheelPrecise = e.Wheel.Y;
+ mouse.WheelPrecise = e.Mouse.Scroll.Y;
};
// Hook keyboard events
MathHelper.Clamp((int)Math.Round(p.Y + dy), 0, Height));
}
- InputDriver.Mouse[0].Position = p;
+ MouseState.X = p.X;
+ MouseState.Y = p.Y;
+ OnMouseMove();
}
break;
factor = 1.0f / scrollFactor; // Problem: Don't know what factor to use here, but this seems to work.
}
- InputDriver.Mouse[0].WheelPrecise += scrollingDelta * factor;
+ MouseState.SetScrollRelative(0, scrollingDelta * factor);
+ OnMouseWheel();
}
break;
case NSEventType.OtherMouseDown:
{
var buttonNumber = Cocoa.SendInt(e, selButtonNumber);
- InputDriver.Mouse[0][GetMouseButton(buttonNumber)] = true;
+ MouseState[GetMouseButton(buttonNumber)] = true;
+ OnMouseDown();
}
break;
case NSEventType.OtherMouseUp:
{
var buttonNumber = Cocoa.SendInt(e, selButtonNumber);
- InputDriver.Mouse[0][GetMouseButton(buttonNumber)] = false;
+ MouseState[GetMouseButton(buttonNumber)] = false;
+ OnMouseUp();
}
break;
}
break;
case HIDUsageGD.Wheel:
- mouse.State.WheelPrecise += v_int;
+ mouse.State.SetScrollRelative(0, v_int);
break;
}
break;
case HIDPage.Button:
mouse.State[OpenTK.Input.MouseButton.Left + usage - 1] = v_int == 1;
break;
+
+ case HIDPage.Consumer:
+ switch ((HIDUsageCD)usage)
+ {
+ case HIDUsageCD.ACPan:
+ mouse.State.SetScrollRelative(v_int, 0);
+ break;
+ }
+ break;
}
}
VendorDefinedStart = 0xFF00
}
+ // Consumer electronic devices
+ enum HIDUsageCD
+ {
+ ACPan = 0x0238
+ }
+
// Generic desktop usage
enum HIDUsageGD
{
{
readonly LegacyInputDriver LegacyInputDriver;
- readonly protected MouseButtonEventArgs MouseDownArgs = new MouseButtonEventArgs();
- readonly protected MouseButtonEventArgs MouseUpArgs = new MouseButtonEventArgs();
- readonly protected MouseMoveEventArgs MouseMoveArgs = new MouseMoveEventArgs();
- readonly protected MouseWheelEventArgs MouseWheelArgs = new MouseWheelEventArgs();
+ readonly MouseButtonEventArgs MouseDownArgs = new MouseButtonEventArgs();
+ readonly MouseButtonEventArgs MouseUpArgs = new MouseButtonEventArgs();
+ readonly MouseMoveEventArgs MouseMoveArgs = new MouseMoveEventArgs();
+ readonly MouseWheelEventArgs MouseWheelArgs = new MouseWheelEventArgs();
- readonly protected KeyboardKeyEventArgs KeyDownArgs = new KeyboardKeyEventArgs();
- readonly protected KeyboardKeyEventArgs KeyUpArgs = new KeyboardKeyEventArgs();
- readonly protected KeyPressEventArgs KeyPressArgs = new KeyPressEventArgs((char)0);
+ protected readonly KeyboardKeyEventArgs KeyDownArgs = new KeyboardKeyEventArgs();
+ protected readonly KeyboardKeyEventArgs KeyUpArgs = new KeyboardKeyEventArgs();
+ protected readonly 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();
+ MouseState PreviousMouseState = new MouseState();
internal NativeWindowBase()
{
LegacyInputDriver = new LegacyInputDriver(this);
+ MouseState.SetIsConnected(true);
+ PreviousMouseState.SetIsConnected(true);
}
#region Protected Members
MouseEnter(this, e);
}
- protected void OnMouseDown(MouseButtonEventArgs e)
+ protected void OnMouseDown()
{
- MouseDown(this, e);
+ var e = MouseDownArgs;
+ e.Mouse = MouseState;
+
+ // Find which button caused this event
+ for (MouseButton b = MouseButton.Left; b < MouseButton.LastButton; b++)
+ {
+ if (!PreviousMouseState[b] && MouseState[b])
+ {
+ e.Button = b;
+ PreviousMouseState = MouseState;
+ MouseDown(this, e);
+ return;
+ }
+ }
+
+ Debug.WriteLine("OnMouseDown called without pressing a button");
}
- protected void OnMouseUp(MouseButtonEventArgs e)
+ protected void OnMouseUp()
{
- MouseUp(this, e);
+ var e = MouseUpArgs;
+ e.Mouse = MouseState;
+
+ // Find which button caused this event
+ for (MouseButton b = MouseButton.Left; b < MouseButton.LastButton; b++)
+ {
+ if (PreviousMouseState[b] && !MouseState[b])
+ {
+ e.Button = b;
+ PreviousMouseState = MouseState;
+ MouseUp(this, e);
+ return;
+ }
+ }
+
+ Debug.WriteLine("OnMouseUp called without pressing a button");
}
- protected void OnMouseMove(MouseMoveEventArgs e)
+ protected void OnMouseMove()
{
+ var e = MouseMoveArgs;
+ e.Mouse = MouseState;
+ e.XDelta = MouseState.X - PreviousMouseState.X;
+ e.YDelta = MouseState.Y - PreviousMouseState.Y;
+
+ if (e.XDelta == 0 && e.YDelta == 0)
+ {
+ Debug.WriteLine("OnMouseMove called without moving the mouse");
+ }
+
+ PreviousMouseState = MouseState;
MouseMove(this, e);
}
- protected void OnMouseWheel(MouseWheelEventArgs e)
+ protected void OnMouseWheel()
{
+ var e = MouseWheelArgs;
+ e.Mouse = MouseState;
+ e.ValuePrecise = MouseState.Scroll.Y;
+ e.DeltaPrecise = MouseState.Scroll.Y - PreviousMouseState.Scroll.Y;
+
+ if (e.DeltaPrecise == 0)
+ {
+ Debug.WriteLine("OnMouseWheel called without moving the mouse wheel.");
+ }
+
+ PreviousMouseState = MouseState;
MouseWheel(this, e);
}
public void ProcessWheelEvent(MouseWheelEvent wheel)
{
- state.WheelPrecise += wheel.Y;
+ state.SetScrollRelative(0, wheel.Y);
}
public void ProcessMouseEvent(MouseMotionEvent motion)
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;
+ window.MouseState[Sdl2Mouse.TranslateButton(ev.Button)] = button_pressed;
+ window.MouseState.X = ev.X;
+ window.MouseState.Y = ev.Y;
if (button_pressed)
{
- window.OnMouseDown(e);
+ window.OnMouseDown();
}
else
{
- window.OnMouseUp(e);
+ window.OnMouseUp();
}
}
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)
- {
- 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);
- }
+ window.MouseState.X = ev.X;
+ window.MouseState.Y = ev.Y;
+ window.OnMouseMove();
}
static void ProcessMouseWheelEvent(Sdl2NativeWindow window, MouseWheelEvent ev)
{
- var e = window.MouseWheelArgs;
- e.Wheel.Y = ev.Y;
- e.Wheel.X = ev.X;
- window.OnMouseWheel(e);
+ window.MouseState.SetScrollRelative(ev.X, ev.Y);
+ window.OnMouseWheel();
}
static void ProcessWindowEvent(Sdl2NativeWindow window, WindowEvent e)
BUTTON_5_DOWN = 0x0100,
BUTTON_5_UP = 0x0200,
- WHEEL = 0x0400
+ WHEEL = 0x0400,
+ HWHEEL = 0x0800,
}
#endregion
if (points == 0 || (points == -1 && lastError == Constants.ERROR_POINT_NOT_FOUND))
{
// Just use the mouse move position
- MouseMoveArgs.Position = point;
- OnMouseMove(MouseMoveArgs);
+ MouseState.X = point.X;
+ MouseState.Y = point.Y;
+ OnMouseMove();
}
else if (points == -1)
{
position.Y -= 65536;
}
Functions.ScreenToClient(handle, ref position);
- MouseMoveArgs.Position = position;
- OnMouseMove(MouseMoveArgs);
+ MouseState.X = position.X;
+ MouseState.Y = position.Y;
+ OnMouseMove();
}
}
mouse_last_timestamp = timestamp;
{
// This is due to inconsistent behavior of the WParam value on 64bit arch, whese
// wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
- MouseWheelArgs.Wheel.Y += ((long)wParam << 32 >> 48) / 120.0f;
- OnMouseWheel(MouseWheelArgs);
+ MouseState.SetScrollRelative(0, ((long)wParam << 32 >> 48) / 120.0f);
+ OnMouseWheel();
}
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);
+ MouseState.SetScrollRelative(((long)wParam << 32 >> 48) / 120.0f, 0);
+ OnMouseWheel();
}
void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle);
- MouseDownArgs.Button = MouseButton.Left;
- MouseDownArgs.IsPressed = true;
- OnMouseDown(MouseDownArgs);
+ MouseState[MouseButton.Left] = true;
+ OnMouseDown();
}
void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle);
- MouseDownArgs.Button = MouseButton.Middle;
- MouseDownArgs.IsPressed = true;
- OnMouseDown(MouseDownArgs);
+ MouseState[MouseButton.Middle] = true;
+ OnMouseDown();
}
void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle);
- MouseDownArgs.Button = MouseButton.Right;
- MouseDownArgs.IsPressed = true;
- OnMouseDown(MouseDownArgs);
+ MouseState[MouseButton.Right] = true;
+ OnMouseDown();
}
void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
MouseButton button =
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
MouseButton.Button1 : MouseButton.Button2;
- MouseDownArgs.Button = button;
- MouseDownArgs.IsPressed = true;
- OnMouseDown(MouseDownArgs);
+ MouseState[button] = true;
+ OnMouseDown();
}
void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture();
- MouseDownArgs.Button = MouseButton.Left;
- MouseDownArgs.IsPressed = false;
- OnMouseUp(MouseUpArgs);
+ MouseState[MouseButton.Left] = false;
+ OnMouseUp();
}
void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture();
- MouseDownArgs.Button = MouseButton.Middle;
- MouseDownArgs.IsPressed = false;
- OnMouseUp(MouseUpArgs);
+ MouseState[MouseButton.Middle] = false;
+ OnMouseUp();
}
void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture();
- MouseDownArgs.Button = MouseButton.Right;
- MouseDownArgs.IsPressed = false;
- OnMouseUp(MouseUpArgs);
+ MouseState[MouseButton.Right] = false;
+ OnMouseUp();
}
void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
MouseButton button =
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
MouseButton.Button1 : MouseButton.Button2;
- MouseDownArgs.Button = button;
- MouseDownArgs.IsPressed = false;
- OnMouseUp(MouseUpArgs);
+ MouseState[button] = false;
+ OnMouseUp();
}
void HandleKeyboard(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
}
if ((raw.ButtonFlags & RawInputMouseState.WHEEL) != 0)
- mouse.WheelPrecise += (short)raw.ButtonData / 120.0f;
+ mouse.SetScrollRelative(0, (short)raw.ButtonData / 120.0f);
+
+ if ((raw.ButtonFlags & RawInputMouseState.HWHEEL) != 0)
+ mouse.SetScrollRelative((short)raw.ButtonData / 120.0f, 0);
if ((raw.Flags & RawMouseFlags.MOUSE_MOVE_ABSOLUTE) != 0)
{
case 1: state.EnableBit((int)MouseButton.Left); break;
case 2: state.EnableBit((int)MouseButton.Middle); break;
case 3: state.EnableBit((int)MouseButton.Right); break;
- case 4: state.WheelPrecise++; break;
- case 5: state.WheelPrecise--; break;
+ case 4: state.SetScrollRelative(0, 1); break;
+ case 5: state.SetScrollRelative(0, -1); break;
case 6: state.EnableBit((int)MouseButton.Button1); break;
case 7: state.EnableBit((int)MouseButton.Button2); break;
case 8: state.EnableBit((int)MouseButton.Button3); break;