Permalink
Browse files

[X11] Implemented high-resolution scroll events

  • Loading branch information...
1 parent 9255fdc commit c6dafbccbaf07b9234ea4617dc7a5e242f17e832 @thefiddler thefiddler committed May 13, 2014
View
119 Source/OpenTK/Input/MouseScroll.cs
@@ -0,0 +1,119 @@
+#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("[X={0:0.00}, Y={1:0.00}]", 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
+ }
+}
+
View
31 Source/OpenTK/Platform/X11/X11GLNative.cs
@@ -132,6 +132,7 @@ internal sealed class X11GLNative : NativeWindowBase
readonly bool xi2_supported;
readonly int xi2_opcode;
+ readonly int xi2_version;
#endregion
@@ -243,6 +244,7 @@ internal sealed class X11GLNative : NativeWindowBase
if (xi2_supported)
{
xi2_opcode = XI2Mouse.XIOpCode;
+ xi2_version = XI2Mouse.XIVersion;
}
exists = true;
@@ -918,23 +920,37 @@ public override void ProcessEvents()
case XEventName.ButtonPress:
{
- int dx, dy;
+ float dx, dy;
MouseButton button = X11KeyMap.TranslateButton(e.ButtonEvent.button, out dx, out dy);
if (button != MouseButton.LastButton)
{
OnMouseDown(button);
}
- else if (dx != 0 || dy != 0)
+
+ if (xi2_version >= 210)
{
+ // High resolution scroll events supported.
+ // This code is implemented in XI2Mouse.GetCursorState().
+ // Instead of reimplementing this functionality, just
+ // use the values from there.
+ MouseState state = Mouse.GetCursorState();
+ dx = state.Scroll.X - MouseState.Scroll.X;
+ dy = state.Scroll.Y - MouseState.Scroll.Y;
+ }
+
+ if (dx != 0 || dy != 0)
+ {
+ // High resolution scroll events not supported
+ // fallback to the old Button4-7 scroll buttons
OnMouseWheel(dx, dy);
}
}
break;
case XEventName.ButtonRelease:
{
- int dx, dy;
+ float dx, dy;
MouseButton button = X11KeyMap.TranslateButton(e.ButtonEvent.button, out dx, out dy);
if (button != MouseButton.LastButton)
{
@@ -1003,7 +1019,7 @@ public override void ProcessEvents()
// RefreshWindowBorders();
//}
break;
-
+
default:
//Debug.WriteLine(String.Format("{0} event was not handled", e.type));
break;
@@ -1499,11 +1515,8 @@ public override bool CursorVisible
void GrabMouse()
{
Functions.XGrabPointer(window.Display, window.Handle, false,
- EventMask.PointerMotionMask |
- EventMask.ButtonMotionMask | EventMask.Button1MotionMask |
- EventMask.Button2MotionMask | EventMask.Button3MotionMask |
- EventMask.Button4MotionMask | EventMask.Button5MotionMask |
- EventMask.ButtonPressMask | EventMask.ButtonReleaseMask,
+ EventMask.PointerMotionMask | EventMask.ButtonPressMask |
+ EventMask.ButtonReleaseMask,
GrabMode.GrabModeAsync, GrabMode.GrabModeAsync,
window.Handle, EmptyCursor, IntPtr.Zero);
}
View
2 Source/OpenTK/Platform/X11/X11KeyMap.cs
@@ -388,7 +388,7 @@ internal static bool TranslateKey(ref XKeyEvent e, out Key key)
return key != Key.Unknown;
}
- internal static MouseButton TranslateButton(int button, out int wheelx, out int wheely)
+ internal static MouseButton TranslateButton(int button, out float wheelx, out float wheely)
{
wheelx = 0;
wheely = 0;
View
34 Source/OpenTK/Platform/X11/XI2Mouse.cs
@@ -73,6 +73,7 @@ class XIMouse
internal readonly X11WindowInfo window;
internal static int XIOpCode { get; private set; }
+ internal static int XIVersion { get; private set; }
static readonly Functions.EventPredicate PredicateImpl = IsEventValid;
readonly IntPtr Predicate = Marshal.GetFunctionPointerForDelegate(PredicateImpl);
@@ -172,6 +173,7 @@ internal static bool IsSupported(IntPtr display)
{
if (XI.QueryVersion(display, ref major, ref minor) == ErrorCodes.Success)
{
+ XIVersion = major * 100 + minor * 10;
return true;
}
minor--;
@@ -385,15 +387,13 @@ void ProcessRawEvent(ref XGenericEventCookie cookie)
case 1: d.State.EnableBit((int)MouseButton.Left); break;
case 2: d.State.EnableBit((int)MouseButton.Middle); break;
case 3: d.State.EnableBit((int)MouseButton.Right); break;
- case 6: d.State.EnableBit((int)MouseButton.Button1); break;
- case 7: d.State.EnableBit((int)MouseButton.Button2); break;
- case 8: d.State.EnableBit((int)MouseButton.Button3); break;
- case 9: d.State.EnableBit((int)MouseButton.Button4); break;
- case 10: d.State.EnableBit((int)MouseButton.Button5); break;
- case 11: d.State.EnableBit((int)MouseButton.Button6); break;
- case 12: d.State.EnableBit((int)MouseButton.Button7); break;
- case 13: d.State.EnableBit((int)MouseButton.Button8); break;
- case 14: d.State.EnableBit((int)MouseButton.Button9); break;
+ case 8: d.State.EnableBit((int)MouseButton.Button1); break;
+ case 9: d.State.EnableBit((int)MouseButton.Button2); break;
+ case 10: d.State.EnableBit((int)MouseButton.Button3); break;
+ case 11: d.State.EnableBit((int)MouseButton.Button4); break;
+ case 12: d.State.EnableBit((int)MouseButton.Button5); break;
+ case 13: d.State.EnableBit((int)MouseButton.Button6); break;
+ case 14: d.State.EnableBit((int)MouseButton.Button7); break;
}
break;
@@ -403,15 +403,13 @@ void ProcessRawEvent(ref XGenericEventCookie cookie)
case 1: d.State.DisableBit((int)MouseButton.Left); break;
case 2: d.State.DisableBit((int)MouseButton.Middle); break;
case 3: d.State.DisableBit((int)MouseButton.Right); break;
- case 6: d.State.DisableBit((int)MouseButton.Button1); break;
- case 7: d.State.DisableBit((int)MouseButton.Button2); break;
- case 8: d.State.DisableBit((int)MouseButton.Button3); break;
- case 9: d.State.DisableBit((int)MouseButton.Button4); break;
- case 10: d.State.DisableBit((int)MouseButton.Button5); break;
- case 11: d.State.DisableBit((int)MouseButton.Button6); break;
- case 12: d.State.DisableBit((int)MouseButton.Button7); break;
- case 13: d.State.DisableBit((int)MouseButton.Button8); break;
- case 14: d.State.DisableBit((int)MouseButton.Button9); break;
+ case 8: d.State.DisableBit((int)MouseButton.Button1); break;
+ case 9: d.State.DisableBit((int)MouseButton.Button2); break;
+ case 10: d.State.DisableBit((int)MouseButton.Button3); break;
+ case 11: d.State.DisableBit((int)MouseButton.Button4); break;
+ case 12: d.State.DisableBit((int)MouseButton.Button5); break;
+ case 13: d.State.DisableBit((int)MouseButton.Button6); break;
+ case 14: d.State.DisableBit((int)MouseButton.Button7); break;
}
break;
}

0 comments on commit c6dafbc

Please sign in to comment.