[X11] Implemented high-resolution scroll events

This commit is contained in:
thefiddler 2014-05-13 23:23:51 +02:00
parent 9255fdcdb4
commit c6dafbccba
4 changed files with 158 additions and 28 deletions

View file

@ -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 file

@ -132,6 +132,7 @@ namespace OpenTK.Platform.X11
readonly bool xi2_supported;
readonly int xi2_opcode;
readonly int xi2_version;
#endregion
@ -243,6 +244,7 @@ namespace OpenTK.Platform.X11
if (xi2_supported)
{
xi2_opcode = XI2Mouse.XIOpCode;
xi2_version = XI2Mouse.XIVersion;
}
exists = true;
@ -918,15 +920,29 @@ namespace OpenTK.Platform.X11
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);
}
}
@ -934,7 +950,7 @@ namespace OpenTK.Platform.X11
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 @@ namespace OpenTK.Platform.X11
// RefreshWindowBorders();
//}
break;
default:
//Debug.WriteLine(String.Format("{0} event was not handled", e.type));
break;
@ -1499,11 +1515,8 @@ namespace OpenTK.Platform.X11
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 file

@ -388,7 +388,7 @@ namespace OpenTK.Platform.X11
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 file

@ -73,6 +73,7 @@ namespace OpenTK.Platform.X11
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 @@ namespace OpenTK.Platform.X11
{
if (XI.QueryVersion(display, ref major, ref minor) == ErrorCodes.Success)
{
XIVersion = major * 100 + minor * 10;
return true;
}
minor--;
@ -385,15 +387,13 @@ namespace OpenTK.Platform.X11
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 @@ namespace OpenTK.Platform.X11
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;
}