Merge pull request #114 from thefiddler/nativewindow
INativeWindow cleanup and consolidation
This commit is contained in:
commit
cd7342b688
40 changed files with 2387 additions and 1916 deletions
|
@ -549,7 +549,7 @@
|
|||
<None Include="Data\Audio\the_ring_that_fell.wav">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Data\Textures\cursor.png">
|
||||
<None Include="Data\Textures\cursor.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<EmbeddedResource Include="OpenGL\1.x\OpenGLDiagnostics.rtf" />
|
||||
|
@ -572,6 +572,7 @@
|
|||
<Link>Dependencies\x64\libSDL2.dylib</Link>
|
||||
</None>
|
||||
<Compile Include="OpenTK\Test\ExternalContext.cs" />
|
||||
<Compile Include="OpenTK\Test\PointToClient.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
|
|
@ -26,6 +26,28 @@ namespace Examples.Tests
|
|||
bool mouse_in_window = false;
|
||||
bool viewport_changed = true;
|
||||
|
||||
MouseCursor Pencil;
|
||||
|
||||
// legacy GameWindow.Mouse.* events
|
||||
Vector4 mousedevice_pos;
|
||||
int mousedevice_buttons;
|
||||
MouseState mousedevice_state;
|
||||
|
||||
// new GameWindow.Mouse* events
|
||||
Vector4 mouse_pos;
|
||||
int mouse_buttons;
|
||||
MouseState mouse_state;
|
||||
|
||||
// legacy GameWindow.Keyboard.Key* events
|
||||
Dictionary<Key, int> legacy_keyboard_keys = new Dictionary<Key, int>();
|
||||
KeyboardState legacy_keyboard_state;
|
||||
KeyModifiers legacy_keyboard_modifiers;
|
||||
|
||||
//new GameWindow.Key* events
|
||||
Dictionary<Key, int> keyboard_keys = new Dictionary<Key, int>();
|
||||
KeyboardState keyboard_state;
|
||||
KeyModifiers keyboard_modifiers;
|
||||
|
||||
// time drift
|
||||
Stopwatch watch = new Stopwatch();
|
||||
double update_time, render_time;
|
||||
|
@ -42,8 +64,6 @@ namespace Examples.Tests
|
|||
double variable_refresh_timestep_pos = -1;
|
||||
double fixed_update_timestep_pos = -1;
|
||||
|
||||
KeyModifiers modifiers;
|
||||
|
||||
public GameWindowStates()
|
||||
: base(800, 600, GraphicsMode.Default)
|
||||
{
|
||||
|
@ -52,16 +72,26 @@ namespace Examples.Tests
|
|||
KeyDown += KeyDownHandler;
|
||||
KeyUp += KeyUpHandler;
|
||||
KeyPress += KeyPressHandler;
|
||||
Keyboard.KeyDown += KeyboardDeviceDownHandler;
|
||||
Keyboard.KeyUp += KeyboardDeviceUpHandler;
|
||||
|
||||
MouseEnter += delegate { mouse_in_window = true; };
|
||||
MouseLeave += delegate { mouse_in_window = false; };
|
||||
|
||||
Mouse.Move += MouseMoveHandler;
|
||||
Mouse.ButtonDown += MouseButtonHandler;
|
||||
Mouse.ButtonUp += MouseButtonHandler;
|
||||
Mouse.Move += MouseDeviceMoveHandler;
|
||||
Mouse.WheelChanged += MouseDeviceWheelHandler;
|
||||
Mouse.ButtonDown += MouseDeviceButtonHandler;
|
||||
Mouse.ButtonUp += MouseDeviceButtonHandler;
|
||||
|
||||
MouseMove += MouseMoveHandler;
|
||||
MouseWheel += MouseWheelHandler;
|
||||
MouseDown += MouseButtonHandler;
|
||||
MouseUp += MouseButtonHandler;
|
||||
}
|
||||
|
||||
private void KeyPressHandler(object sender, KeyPressEventArgs e)
|
||||
#region Keyboard Events
|
||||
|
||||
void KeyPressHandler(object sender, KeyPressEventArgs e)
|
||||
{
|
||||
if (TypedText.Length > 32)
|
||||
TypedText.Remove(0, 1);
|
||||
|
@ -108,27 +138,118 @@ namespace Examples.Tests
|
|||
case Key.BracketRight: TargetUpdateFrequency++; break;
|
||||
case Key.Comma: TargetRenderFrequency--; break;
|
||||
case Key.Period: TargetRenderFrequency++; break;
|
||||
|
||||
case Key.Space:
|
||||
CursorVisible = !CursorVisible;
|
||||
break;
|
||||
}
|
||||
modifiers = e.Modifiers;
|
||||
|
||||
if (!keyboard_keys.ContainsKey(e.Key))
|
||||
{
|
||||
keyboard_keys.Add(e.Key, 0);
|
||||
}
|
||||
keyboard_keys[e.Key] = e.IsRepeat ? 1 : 0;
|
||||
keyboard_modifiers = e.Modifiers;
|
||||
keyboard_state = e.Keyboard;
|
||||
}
|
||||
|
||||
void KeyUpHandler(object sender, KeyboardKeyEventArgs e)
|
||||
{
|
||||
modifiers = e.Modifiers;
|
||||
keyboard_keys.Remove(e.Key);
|
||||
keyboard_modifiers = e.Modifiers;
|
||||
keyboard_state = e.Keyboard;
|
||||
}
|
||||
|
||||
void KeyboardDeviceDownHandler(object sender, KeyboardKeyEventArgs e)
|
||||
{
|
||||
if (!legacy_keyboard_keys.ContainsKey(e.Key))
|
||||
{
|
||||
legacy_keyboard_keys.Add(e.Key, 0);
|
||||
}
|
||||
legacy_keyboard_keys[e.Key] = e.IsRepeat ? 1 : 0;
|
||||
legacy_keyboard_modifiers = e.Modifiers;
|
||||
legacy_keyboard_state = e.Keyboard;
|
||||
}
|
||||
|
||||
void KeyboardDeviceUpHandler(object sender, KeyboardKeyEventArgs e)
|
||||
{
|
||||
legacy_keyboard_keys.Remove(e.Key);
|
||||
legacy_keyboard_modifiers = e.Modifiers;
|
||||
legacy_keyboard_state = e.Keyboard;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MouseDevice events
|
||||
|
||||
void MouseDeviceMoveHandler(object sender, MouseMoveEventArgs e)
|
||||
{
|
||||
mousedevice_pos.X = e.X;
|
||||
mousedevice_pos.Y = e.Y;
|
||||
mousedevice_pos.Z = e.Mouse.Scroll.X;
|
||||
mousedevice_pos.W = e.Mouse.Scroll.Y;
|
||||
mousedevice_state = e.Mouse;
|
||||
}
|
||||
|
||||
void MouseDeviceButtonHandler(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.IsPressed)
|
||||
{
|
||||
mousedevice_buttons |= 1 << (int)e.Button;
|
||||
Cursor = Pencil;
|
||||
}
|
||||
else
|
||||
{
|
||||
mousedevice_buttons &= ~(1 << (int)e.Button);
|
||||
Cursor = MouseCursor.Default;
|
||||
}
|
||||
mousedevice_state = e.Mouse;
|
||||
}
|
||||
|
||||
void MouseDeviceWheelHandler(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
mousedevice_pos.Z = e.Mouse.Scroll.X;
|
||||
mousedevice_pos.W = e.Mouse.Scroll.Y;
|
||||
mousedevice_state = e.Mouse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mouse events
|
||||
|
||||
void MouseMoveHandler(object sender, MouseMoveEventArgs e)
|
||||
{
|
||||
mouse_pos.X = e.X;
|
||||
mouse_pos.Y = e.Y;
|
||||
mouse_pos.Z = e.Mouse.Scroll.X;
|
||||
mouse_pos.W = e.Mouse.Scroll.Y;
|
||||
mouse_state = e.Mouse;
|
||||
}
|
||||
|
||||
void MouseButtonHandler(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButton.Left && e.IsPressed)
|
||||
if (e.IsPressed)
|
||||
{
|
||||
CursorVisible = false;
|
||||
mouse_buttons |= 1 << (int)e.Button;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_buttons &= ~(1 << (int)e.Button);
|
||||
}
|
||||
mouse_state = e.Mouse;
|
||||
}
|
||||
|
||||
void MouseWheelHandler(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
mouse_pos.Z = e.Mouse.Scroll.X;
|
||||
mouse_pos.W = e.Mouse.Scroll.Y;
|
||||
mouse_state = e.Mouse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
static int Clamp(int val, int min, int max)
|
||||
{
|
||||
return val > max ? max : val < min ? min : val;
|
||||
|
@ -145,10 +266,23 @@ namespace Examples.Tests
|
|||
return offset + gfx.MeasureString(str, TextFont).Width;
|
||||
}
|
||||
|
||||
static void KeyboardStateToString(KeyboardState state, StringBuilder sb)
|
||||
{
|
||||
for (int key_index = 0; key_index < (int)Key.LastKey; key_index++)
|
||||
{
|
||||
Key k = (Key)key_index;
|
||||
if (state[k])
|
||||
{
|
||||
sb.Append(k);
|
||||
sb.Append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DrawKeyboards(Graphics gfx, int line)
|
||||
{
|
||||
line++;
|
||||
DrawString(gfx, String.Format("Keyboard ({0}):", modifiers), line++);
|
||||
DrawString(gfx, "Keyboard:", line++);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
var state = OpenTK.Input.Keyboard.GetState(i);
|
||||
|
@ -157,15 +291,7 @@ namespace Examples.Tests
|
|||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(i);
|
||||
sb.Append(": ");
|
||||
for (int key_index = 0; key_index < (int)Key.LastKey; key_index++)
|
||||
{
|
||||
Key k = (Key)key_index;
|
||||
if (state[k])
|
||||
{
|
||||
sb.Append(k);
|
||||
sb.Append(" ");
|
||||
}
|
||||
}
|
||||
KeyboardStateToString(state, sb);
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +327,112 @@ namespace Examples.Tests
|
|||
return line;
|
||||
}
|
||||
|
||||
int DrawKeyboardDevice(Graphics gfx, int line)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("KeyboardDevice: ");
|
||||
for (Key key = 0; key < Key.LastKey; key++)
|
||||
{
|
||||
if (Keyboard[key])
|
||||
{
|
||||
sb.Append(key);
|
||||
sb.Append(" ");
|
||||
}
|
||||
}
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
sb.Remove(0, sb.Length);
|
||||
sb.Append("KeyboardDevice events: [");
|
||||
sb.Append(legacy_keyboard_modifiers);
|
||||
sb.Append("] ");
|
||||
foreach (var pair in legacy_keyboard_keys)
|
||||
{
|
||||
sb.Append(pair.Key);
|
||||
sb.Append(":");
|
||||
sb.Append(pair.Value);
|
||||
sb.Append(" ");
|
||||
}
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
sb.Remove(0, sb.Length);
|
||||
sb.Append("KeyboardDevice state: ");
|
||||
KeyboardStateToString(legacy_keyboard_state, sb);
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
sb.Remove(0, sb.Length);
|
||||
sb.Append("Keyboard events: [");
|
||||
sb.Append(keyboard_modifiers);
|
||||
sb.Append("] ");
|
||||
foreach (var pair in keyboard_keys)
|
||||
{
|
||||
sb.Append(pair.Key);
|
||||
sb.Append(":");
|
||||
sb.Append(pair.Value);
|
||||
sb.Append(" ");
|
||||
}
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
sb.Remove(0, sb.Length);
|
||||
sb.Append("Keyboard state: ");
|
||||
KeyboardStateToString(keyboard_state, sb);
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
int DrawMouseDevice(Graphics gfx, int line)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("MouseDevice: ");
|
||||
sb.AppendFormat("[{0}, {1}, {2:0.00}] ",
|
||||
Mouse.X, Mouse.Y, Mouse.WheelPrecise);
|
||||
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("MouseDevice events: ");
|
||||
sb.AppendFormat("[{0}, {1}, {2:0.00}, {3:0.00}] ",
|
||||
mousedevice_pos.X, mousedevice_pos.Y,
|
||||
mousedevice_pos.Z, mousedevice_pos.W);
|
||||
for (var i = MouseButton.Left; i < MouseButton.LastButton; i++)
|
||||
{
|
||||
if ((mousedevice_buttons & (1 << (int)i)) != 0)
|
||||
{
|
||||
sb.Append(i);
|
||||
sb.Append(" ");
|
||||
}
|
||||
}
|
||||
sb.Append(" ");
|
||||
sb.AppendLine(mousedevice_state.ToString());
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
|
||||
sb.Remove(0, sb.Length);
|
||||
sb.Append("Mouse events: ");
|
||||
sb.AppendFormat("[{0}, {1}, {2:0.00}, {3:0.00}] ",
|
||||
mouse_pos.X, mouse_pos.Y,
|
||||
mouse_pos.Z, mouse_pos.W);
|
||||
for (var i = MouseButton.Left; i < MouseButton.LastButton; i++)
|
||||
{
|
||||
if ((mouse_buttons & (1 << (int)i)) != 0)
|
||||
{
|
||||
sb.Append(i);
|
||||
sb.Append(" ");
|
||||
}
|
||||
}
|
||||
sb.Append(" ");
|
||||
sb.AppendLine(mouse_state.ToString());
|
||||
DrawString(gfx, sb.ToString(), line++);
|
||||
return line;
|
||||
}
|
||||
|
||||
static int DrawLegacyJoysticks(Graphics gfx, IList<JoystickDevice> joysticks, int line)
|
||||
{
|
||||
line++;
|
||||
|
@ -236,6 +468,8 @@ namespace Examples.Tests
|
|||
return line;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||
{
|
||||
double clock_time = watch.Elapsed.TotalSeconds;
|
||||
|
@ -267,7 +501,9 @@ 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 = DrawKeyboardDevice(gfx, line);
|
||||
line = DrawMouseDevice(gfx, line);
|
||||
|
||||
// Timing information
|
||||
line++;
|
||||
|
@ -350,6 +586,17 @@ namespace Examples.Tests
|
|||
{
|
||||
watch.Start();
|
||||
|
||||
using (var bitmap = new Bitmap("Data/Textures/cursor.png"))
|
||||
{
|
||||
var data = bitmap.LockBits(
|
||||
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
System.Drawing.Imaging.ImageLockMode.ReadOnly,
|
||||
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
|
||||
|
||||
Pencil = new OpenTK.MouseCursor(
|
||||
2, 21, data.Width, data.Height, data.Scan0);
|
||||
}
|
||||
|
||||
GL.ClearColor(Color.MidnightBlue);
|
||||
|
||||
GL.Enable(EnableCap.Texture2D);
|
||||
|
|
37
Source/Examples/OpenTK/Test/PointToClient.cs
Normal file
37
Source/Examples/OpenTK/Test/PointToClient.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using OpenTK;
|
||||
|
||||
namespace Examples.Tests
|
||||
{
|
||||
[Example("PointToClient Test", ExampleCategory.OpenTK, "NativeWindow")]
|
||||
public class PointToClientTest
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
using (var window = new NativeWindow())
|
||||
{
|
||||
Trace.WriteLine(String.Format("Window bounds: {0}", window.Bounds));
|
||||
Trace.WriteLine(String.Format("Window client: {0}", window.ClientRectangle));
|
||||
|
||||
Point pclient = new Point(100, 100);
|
||||
Point pscreen = window.PointToScreen(pclient);
|
||||
Point ptest = window.PointToClient(pscreen);
|
||||
Trace.WriteLine(String.Format("Client: {0} -> Screen: {1} -> Client: {2}",
|
||||
pclient, pscreen, ptest));
|
||||
Trace.WriteLine(String.Format("Test {0}",
|
||||
ptest == pclient ? "succeeded" : "failed"));
|
||||
|
||||
pscreen = new Point(100, 100);
|
||||
pclient = window.PointToClient(pscreen);
|
||||
ptest = window.PointToScreen(pclient);
|
||||
Trace.WriteLine(String.Format("Screen: {0} -> Client: {1} -> Screen: {2}",
|
||||
pscreen, pclient, ptest));
|
||||
Trace.WriteLine(String.Format("Test {0}",
|
||||
ptest == pscreen ? "succeeded" : "failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,9 +51,9 @@ namespace OpenTK.Graphics
|
|||
protected string[] EntryPointNamesInstance;
|
||||
|
||||
|
||||
internal protected IntPtr[] _EntryPointsInstance;
|
||||
internal protected byte[] _EntryPointNamesInstance;
|
||||
internal protected int[] _EntryPointNameOffsetsInstance;
|
||||
internal IntPtr[] _EntryPointsInstance;
|
||||
internal byte[] _EntryPointNamesInstance;
|
||||
internal int[] _EntryPointNameOffsetsInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an unmanaged function pointer to the specified function.
|
||||
|
|
|
@ -260,10 +260,26 @@ namespace OpenTK
|
|||
/// </summary>
|
||||
event EventHandler<EventArgs> MouseEnter;
|
||||
|
||||
//event EventHandler<MouseEventArgs> MouseMove;
|
||||
//event EventHandler<MouseEventArgs> MouseWheel;
|
||||
//event EventHandler<MouseEventArgs> MouseDown;
|
||||
//event EventHandler<MouseEventArgs> MouseUp;
|
||||
/// <summary>
|
||||
/// Occurs whenever a <see cref="MouseButton"/> is clicked.
|
||||
/// </summary>
|
||||
event EventHandler<Input.MouseButtonEventArgs> MouseDown;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever a <see cref="MouseButton"/> is released.
|
||||
/// </summary>
|
||||
event EventHandler<Input.MouseButtonEventArgs> MouseUp;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever the mouse cursor is moved;
|
||||
/// </summary>
|
||||
event EventHandler<Input.MouseMoveEventArgs> MouseMove;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever a mouse wheel is moved;
|
||||
/// </summary>
|
||||
event EventHandler<Input.MouseWheelEventArgs> MouseWheel;
|
||||
|
||||
//event EventHandler<MouseEventArgs> MouseClick;
|
||||
//event EventHandler<MouseEventArgs> MouseDoubleClick;
|
||||
|
||||
|
|
|
@ -21,13 +21,11 @@ namespace OpenTK.Input
|
|||
public sealed class KeyboardDevice : IInputDevice
|
||||
{
|
||||
//private IKeyboard keyboard;
|
||||
private bool[] keys = new bool[(int)Key.LastKey];
|
||||
private bool[] scancodes = new bool[256];
|
||||
private string description;
|
||||
private int numKeys, numFKeys, numLeds;
|
||||
private IntPtr devID;
|
||||
private bool repeat;
|
||||
private KeyboardKeyEventArgs args = new KeyboardKeyEventArgs();
|
||||
private KeyboardState state;
|
||||
|
||||
#region --- Constructors ---
|
||||
|
||||
|
@ -44,7 +42,7 @@ namespace OpenTK.Input
|
|||
/// <returns>True if the Key is pressed, false otherwise.</returns>
|
||||
public bool this[Key key]
|
||||
{
|
||||
get { return keys[(int)key]; }
|
||||
get { return state[key]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -52,9 +50,10 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
/// <param name="scancode">The scancode to check.</param>
|
||||
/// <returns>True if the scancode is pressed, false otherwise.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public bool this[uint scancode]
|
||||
{
|
||||
get { return scancodes[scancode]; }
|
||||
get { return scancode < (uint)Key.LastKey && state[(Key)scancode]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -124,7 +123,7 @@ namespace OpenTK.Input
|
|||
/// <summary>
|
||||
/// Occurs when a key is pressed.
|
||||
/// </summary>
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown;
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -133,7 +132,7 @@ namespace OpenTK.Input
|
|||
/// <summary>
|
||||
/// Occurs when a key is released.
|
||||
/// </summary>
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp;
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -185,21 +184,22 @@ namespace OpenTK.Input
|
|||
|
||||
#region --- Internal Methods ---
|
||||
|
||||
#region internal void ClearKeys()
|
||||
|
||||
internal void ClearKeys()
|
||||
internal void HandleKeyDown(object sender, KeyboardKeyEventArgs e)
|
||||
{
|
||||
for (int i = 0; i < keys.Length; i++)
|
||||
keys[i] = false;
|
||||
for (uint i = 0; i < scancodes.Length; i++)
|
||||
scancodes[i] = false;
|
||||
state = e.Keyboard;
|
||||
KeyDown(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal void SetKey(Key key, uint scancode, bool state)
|
||||
internal void HandleKeyUp(object sender, KeyboardKeyEventArgs e)
|
||||
{
|
||||
if (keys[(int)key] != state || KeyRepeat)
|
||||
state = e.Keyboard;
|
||||
KeyUp(this, e);
|
||||
}
|
||||
|
||||
#if false
|
||||
internal void SetKey(Key key, uint scancode, KeyModifiers mods, bool pressed)
|
||||
{
|
||||
if (state[key] != pressed || KeyRepeat)
|
||||
{
|
||||
// limit scancode to 8bits, otherwise the assignment
|
||||
// below will crash randomly
|
||||
|
@ -209,42 +209,22 @@ namespace OpenTK.Input
|
|||
|
||||
if (state && KeyDown != null)
|
||||
{
|
||||
|
||||
args.Key = key;
|
||||
args.ScanCode = scancode;
|
||||
args.Modifiers = GetModifiers();
|
||||
args.Modifiers = mods;
|
||||
KeyDown(this, args);
|
||||
}
|
||||
else if (!state && KeyUp != null)
|
||||
{
|
||||
args.Key = key;
|
||||
args.ScanCode = scancode;
|
||||
args.Modifiers = GetModifiers();
|
||||
args.Modifiers = mods;
|
||||
KeyUp(this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal KeyModifiers GetModifiers()
|
||||
{
|
||||
KeyModifiers mods = 0;
|
||||
|
||||
if (this[Key.AltLeft] || this[Key.AltRight])
|
||||
{
|
||||
mods |= KeyModifiers.Alt;
|
||||
}
|
||||
|
||||
if (this[Key.ControlLeft] || this[Key.ControlRight])
|
||||
{
|
||||
mods |= KeyModifiers.Control;
|
||||
}
|
||||
|
||||
if (this[Key.ShiftLeft] || this[Key.ShiftRight])
|
||||
{
|
||||
mods |= KeyModifiers.Shift;
|
||||
}
|
||||
|
||||
return mods;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ namespace OpenTK.Input
|
|||
#region Fields
|
||||
|
||||
Key key;
|
||||
KeyModifiers mods;
|
||||
uint scancode;
|
||||
bool repeat;
|
||||
KeyboardState state;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -65,7 +65,6 @@ namespace OpenTK.Input
|
|||
public KeyboardKeyEventArgs(KeyboardKeyEventArgs args)
|
||||
{
|
||||
Key = args.Key;
|
||||
ScanCode = args.ScanCode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -87,8 +86,7 @@ namespace OpenTK.Input
|
|||
[CLSCompliant(false)]
|
||||
public uint ScanCode
|
||||
{
|
||||
get { return scancode; }
|
||||
internal set { scancode = value; }
|
||||
get { return (uint)Key; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -97,7 +95,7 @@ namespace OpenTK.Input
|
|||
/// <value><c>true</c> if pressed; otherwise, <c>false</c>.</value>
|
||||
public bool Alt
|
||||
{
|
||||
get { return (mods & KeyModifiers.Alt) != 0; }
|
||||
get { return state[Key.AltLeft] || state[Key.AltRight]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -106,7 +104,7 @@ namespace OpenTK.Input
|
|||
/// <value><c>true</c> if pressed; otherwise, <c>false</c>.</value>
|
||||
public bool Control
|
||||
{
|
||||
get { return (mods & KeyModifiers.Control) != 0; }
|
||||
get { return state[Key.ControlLeft] || state[Key.ControlRight]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -115,7 +113,7 @@ namespace OpenTK.Input
|
|||
/// <value><c>true</c> if pressed; otherwise, <c>false</c>.</value>
|
||||
public bool Shift
|
||||
{
|
||||
get { return (mods & KeyModifiers.Shift) != 0; }
|
||||
get { return state[Key.ShiftLeft] || state[Key.ShiftRight]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -125,8 +123,39 @@ namespace OpenTK.Input
|
|||
/// <value>The modifiers.</value>
|
||||
public KeyModifiers Modifiers
|
||||
{
|
||||
get { return mods; }
|
||||
internal set { mods = value; }
|
||||
get
|
||||
{
|
||||
KeyModifiers mods = 0;
|
||||
mods |= Alt ? KeyModifiers.Alt : 0;
|
||||
mods |= Control ? KeyModifiers.Control : 0;
|
||||
mods |= Shift ? KeyModifiers.Shift : 0;
|
||||
return mods;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current <see cref="OpenTK.Input.KeyboardState"/>.
|
||||
/// </summary>
|
||||
/// <value>The keyboard.</value>
|
||||
public KeyboardState Keyboard
|
||||
{
|
||||
get { return state; }
|
||||
internal set { state = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="System.Boolean"/> indicating whether
|
||||
/// this key event is a repeat.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// true, if this event was caused by the user holding down
|
||||
/// a key; false, if this was caused by the user pressing a
|
||||
/// key for the first time.
|
||||
/// </value>
|
||||
public bool IsRepeat
|
||||
{
|
||||
get { return repeat; }
|
||||
internal set { repeat = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -43,9 +43,6 @@ namespace OpenTK.Input
|
|||
const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
|
||||
// The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
|
||||
unsafe fixed int Keys[NumInts];
|
||||
|
||||
const int CodesSize = 256;
|
||||
unsafe fixed int Codes[CodesSize];
|
||||
bool is_connected;
|
||||
|
||||
#endregion
|
||||
|
@ -61,6 +58,7 @@ namespace OpenTK.Input
|
|||
public bool this[Key key]
|
||||
{
|
||||
get { return IsKeyDown(key); }
|
||||
internal set { SetKeyState(key, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,7 +69,7 @@ namespace OpenTK.Input
|
|||
/// <returns>True if code is pressed; false otherwise.</returns>
|
||||
public bool this[short code]
|
||||
{
|
||||
get { return IsKeyDown(code); }
|
||||
get { return IsKeyDown((Key)code); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -89,7 +87,7 @@ namespace OpenTK.Input
|
|||
/// <param name="code">The scan code to check.</param>
|
||||
public bool IsKeyDown(short code)
|
||||
{
|
||||
return ReadBit(code,true);
|
||||
return code >= 0 && code < (short)Key.LastKey && ReadBit(code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -107,7 +105,7 @@ namespace OpenTK.Input
|
|||
/// <param name="code">The scan code to check.</param>
|
||||
public bool IsKeyUp(short code)
|
||||
{
|
||||
return !ReadBit(code,true);
|
||||
return !IsKeyDown(code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -212,62 +210,51 @@ namespace OpenTK.Input
|
|||
|
||||
#region Internal Members
|
||||
|
||||
internal void SetKeyState(Key key, byte code, bool down)
|
||||
internal void SetKeyState(Key key, bool down)
|
||||
{
|
||||
if (down)
|
||||
{
|
||||
EnableBit((int)key);
|
||||
EnableBit(code,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableBit((int)key);
|
||||
DisableBit(code, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool ReadBit(int offset, bool ScanCode = false)
|
||||
internal bool ReadBit(int offset)
|
||||
{
|
||||
ValidateOffset(offset, ScanCode);
|
||||
ValidateOffset(offset);
|
||||
|
||||
int int_offset = offset / 32;
|
||||
int bit_offset = offset % 32;
|
||||
unsafe
|
||||
{
|
||||
if (ScanCode)
|
||||
fixed (int* c = Codes) { return (*(c + int_offset) & (1 << bit_offset)) != 0u; }
|
||||
else
|
||||
fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
|
||||
fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
|
||||
}
|
||||
}
|
||||
|
||||
internal void EnableBit(int offset, bool ScanCode = false)
|
||||
internal void EnableBit(int offset)
|
||||
{
|
||||
ValidateOffset(offset, ScanCode);
|
||||
ValidateOffset(offset);
|
||||
|
||||
int int_offset = offset / 32;
|
||||
int bit_offset = offset % 32;
|
||||
unsafe
|
||||
{
|
||||
if (ScanCode)
|
||||
fixed (int* c = Codes) { *(c + int_offset) |= 1 << bit_offset; }
|
||||
else
|
||||
fixed (int* k = Keys) { *(k + int_offset) |= 1 << bit_offset; }
|
||||
fixed (int* k = Keys) { *(k + int_offset) |= 1 << bit_offset; }
|
||||
}
|
||||
}
|
||||
|
||||
internal void DisableBit(int offset, bool ScanCode = false)
|
||||
internal void DisableBit(int offset)
|
||||
{
|
||||
ValidateOffset(offset, ScanCode);
|
||||
ValidateOffset(offset);
|
||||
|
||||
int int_offset = offset / 32;
|
||||
int bit_offset = offset % 32;
|
||||
unsafe
|
||||
{
|
||||
if (ScanCode)
|
||||
fixed (int* c = Codes) { *(c + int_offset) &= ~(1 << bit_offset); }
|
||||
else
|
||||
fixed (int* k = Keys) { *(k + int_offset) &= ~(1 << bit_offset); }
|
||||
fixed (int* k = Keys) { *(k + int_offset) &= ~(1 << bit_offset); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,12 +268,6 @@ namespace OpenTK.Input
|
|||
for (int i = 0; i < NumInts; i++)
|
||||
*(k1 + i) |= *(k2 + i);
|
||||
}
|
||||
int* c2 = other.Codes;
|
||||
fixed (int* c1 = Codes)
|
||||
{
|
||||
for (int i = 0; i < CodesSize; i++)
|
||||
*(c1 + i) |= *(c2 + i);
|
||||
}
|
||||
}
|
||||
IsConnected |= other.IsConnected;
|
||||
}
|
||||
|
@ -300,10 +281,10 @@ namespace OpenTK.Input
|
|||
|
||||
#region Private Members
|
||||
|
||||
static void ValidateOffset(int offset, bool ScanCode)
|
||||
static void ValidateOffset(int offset)
|
||||
{
|
||||
if (offset < 0 || offset >= (ScanCode ? 256 : NumInts * IntSize))
|
||||
throw new ArgumentOutOfRangeException("offset");
|
||||
if (offset < 0 || offset >= NumInts * IntSize)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -48,12 +48,8 @@ namespace OpenTK.Input
|
|||
string description;
|
||||
IntPtr id;
|
||||
int numButtons, numWheels;
|
||||
readonly bool[] button_state = new bool[Enum.GetValues(typeof(MouseButton)).Length];
|
||||
float wheel, last_wheel;
|
||||
Point pos = new Point(), last_pos = new Point();
|
||||
MouseMoveEventArgs move_args = new MouseMoveEventArgs();
|
||||
MouseButtonEventArgs button_args = new MouseButtonEventArgs();
|
||||
MouseWheelEventArgs wheel_args = new MouseWheelEventArgs();
|
||||
|
||||
MouseState state;
|
||||
#if COMPAT_REV1519
|
||||
int wheel_last_accessed = 0;
|
||||
Point pos_last_accessed = new Point();
|
||||
|
@ -139,8 +135,7 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
public int Wheel
|
||||
{
|
||||
get { return (int)Math.Round(wheel, MidpointRounding.AwayFromZero); }
|
||||
internal set { WheelPrecise = value; }
|
||||
get { return state.Wheel; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -148,20 +143,7 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
public float WheelPrecise
|
||||
{
|
||||
get { return wheel; }
|
||||
internal set
|
||||
{
|
||||
wheel = value;
|
||||
|
||||
wheel_args.X = pos.X;
|
||||
wheel_args.Y = pos.Y;
|
||||
wheel_args.ValuePrecise = wheel;
|
||||
wheel_args.DeltaPrecise = wheel - last_wheel;
|
||||
|
||||
WheelChanged(this, wheel_args);
|
||||
|
||||
last_wheel = wheel;
|
||||
}
|
||||
get { return state.WheelPrecise; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -173,7 +155,7 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
public int X
|
||||
{
|
||||
get { return pos.X; }
|
||||
get { return state.X; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -185,7 +167,7 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
public int Y
|
||||
{
|
||||
get { return pos.Y; }
|
||||
get { return state.Y; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -201,21 +183,11 @@ namespace OpenTK.Input
|
|||
{
|
||||
get
|
||||
{
|
||||
return button_state[(int)button];
|
||||
return state[button];
|
||||
}
|
||||
internal set
|
||||
{
|
||||
bool previous_state = button_state[(int)button];
|
||||
button_state[(int)button] = value;
|
||||
|
||||
button_args.X = pos.X;
|
||||
button_args.Y = pos.Y;
|
||||
button_args.Button = button;
|
||||
button_args.IsPressed = value;
|
||||
if (value && !previous_state)
|
||||
ButtonDown(this, button_args);
|
||||
else if (!value && previous_state)
|
||||
ButtonUp(this, button_args);
|
||||
state[button] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,26 +197,29 @@ namespace OpenTK.Input
|
|||
|
||||
#region --- Internal Members ---
|
||||
|
||||
#region internal Point Position
|
||||
|
||||
/// <summary>
|
||||
/// Sets a System.Drawing.Point representing the absolute position of the pointer, in window pixel coordinates.
|
||||
/// </summary>
|
||||
internal Point Position
|
||||
internal void HandleMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
set
|
||||
{
|
||||
pos = value;
|
||||
move_args.X = pos.X;
|
||||
move_args.Y = pos.Y;
|
||||
move_args.XDelta = pos.X - last_pos.X;
|
||||
move_args.YDelta = pos.Y - last_pos.Y;
|
||||
Move(this, move_args);
|
||||
last_pos = pos;
|
||||
}
|
||||
state = e.Mouse;
|
||||
ButtonDown(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
internal void HandleMouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
state = e.Mouse;
|
||||
ButtonUp(this, e);
|
||||
}
|
||||
|
||||
internal void HandleMouseMove(object sender, MouseMoveEventArgs e)
|
||||
{
|
||||
state = e.Mouse;
|
||||
Move(this, e);
|
||||
}
|
||||
|
||||
internal void HandleMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
state = e.Mouse;
|
||||
WheelChanged(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -309,8 +284,8 @@ namespace OpenTK.Input
|
|||
{
|
||||
get
|
||||
{
|
||||
int result = (int)Math.Round(wheel - wheel_last_accessed, MidpointRounding.AwayFromZero);
|
||||
wheel_last_accessed = (int)wheel;
|
||||
int result = (int)Math.Round(state.WheelPrecise - wheel_last_accessed, MidpointRounding.AwayFromZero);
|
||||
wheel_last_accessed = state.Wheel;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -327,8 +302,8 @@ namespace OpenTK.Input
|
|||
{
|
||||
get
|
||||
{
|
||||
int result = pos.X - pos_last_accessed.X;
|
||||
pos_last_accessed.X = pos.X;
|
||||
int result = state.X - pos_last_accessed.X;
|
||||
pos_last_accessed.X = state.X;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -345,8 +320,8 @@ namespace OpenTK.Input
|
|||
{
|
||||
get
|
||||
{
|
||||
int result = pos.Y - pos_last_accessed.Y;
|
||||
pos_last_accessed.Y = pos.Y;
|
||||
int result = state.Y - pos_last_accessed.Y;
|
||||
pos_last_accessed.Y = state.Y;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -357,286 +332,4 @@ namespace OpenTK.Input
|
|||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance.
|
||||
/// </summary>
|
||||
public MouseEventArgs()
|
||||
{
|
||||
}
|
||||
|
||||
/// <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 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 a System.Drawing.Points representing the location of the mouse for the event.
|
||||
/// </summary>
|
||||
public Point Position { get { return new Point(x, 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>
|
||||
/// The mouse button for the 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 pressed; } internal set { pressed = value; } }
|
||||
|
||||
#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 value;
|
||||
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)
|
||||
{
|
||||
this.value = 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(value, 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 value; } internal set { this.value = 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
|
||||
}
|
||||
|
|
369
Source/OpenTK/Input/MouseEventArgs.cs
Normal file
369
Source/OpenTK/Input/MouseEventArgs.cs
Normal file
|
@ -0,0 +1,369 @@
|
|||
#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; }
|
||||
}
|
||||
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
|
119
Source/OpenTK/Input/MouseScrollWheel.cs
Normal file
119
Source/OpenTK/Input/MouseScrollWheel.cs
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -38,13 +38,9 @@ namespace OpenTK.Input
|
|||
{
|
||||
#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
|
||||
|
@ -93,7 +89,7 @@ namespace OpenTK.Input
|
|||
/// </summary>
|
||||
public int Wheel
|
||||
{
|
||||
get { return (int)Math.Round(wheel, MidpointRounding.AwayFromZero); }
|
||||
get { return (int)Math.Round(scroll.Y, MidpointRounding.AwayFromZero); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -101,11 +97,16 @@ namespace OpenTK.Input
|
|||
/// </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>
|
||||
|
@ -253,13 +254,18 @@ namespace OpenTK.Input
|
|||
/// </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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents the current <see cref="OpenTK.Input.MouseState"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="System.String"/> that represents the current <see cref="OpenTK.Input.MouseState"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string b = Convert.ToString(buttons, 2).PadLeft(10, '0');
|
||||
return String.Format("[MouseState: X={0}, Y={1}, Scroll={2}, Buttons={3}, IsConnected={4}]",
|
||||
X, Y, Scroll, b, IsConnected);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -269,64 +275,28 @@ namespace OpenTK.Input
|
|||
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;
|
||||
X += other.X;
|
||||
Y += other.Y;
|
||||
IsConnected |= other.IsConnected;
|
||||
}
|
||||
buttons |= other.buttons;
|
||||
SetScrollRelative(other.scroll.X, other.scroll.Y);
|
||||
X += other.X;
|
||||
Y += other.Y;
|
||||
IsConnected |= other.IsConnected;
|
||||
}
|
||||
|
||||
internal void SetIsConnected(bool value)
|
||||
|
@ -334,13 +304,29 @@ namespace OpenTK.Input
|
|||
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");
|
||||
}
|
||||
|
||||
|
@ -355,18 +341,11 @@ namespace OpenTK.Input
|
|||
/// <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
|
||||
|
|
|
@ -163,12 +163,7 @@ namespace OpenTK
|
|||
/// </returns>
|
||||
public Point PointToScreen(Point point)
|
||||
{
|
||||
// Here we use the fact that PointToClient just translates the point, and PointToScreen
|
||||
// should perform the inverse operation.
|
||||
Point trans = PointToClient(Point.Empty);
|
||||
point.X -= trans.X;
|
||||
point.Y -= trans.Y;
|
||||
return point;
|
||||
return implementation.PointToScreen(point);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -680,6 +675,26 @@ namespace OpenTK
|
|||
/// </summary>
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a <see cref="MouseButton"/> is pressed.
|
||||
/// </summary>
|
||||
public event EventHandler<MouseButtonEventArgs> MouseDown = delegate { };
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a <see cref="MouseButton"/> is released.
|
||||
/// </summary>
|
||||
public event EventHandler<MouseButtonEventArgs> MouseUp = delegate { };
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever the mouse is moved.
|
||||
/// </summary>
|
||||
public event EventHandler<MouseMoveEventArgs> MouseMove = delegate { };
|
||||
|
||||
/// <summary>
|
||||
/// Occurs whenever a mouse wheel is moved;
|
||||
/// </summary>
|
||||
public event EventHandler<MouseWheelEventArgs> MouseWheel = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
@ -902,6 +917,54 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="MouseDown"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
/// A <see cref="MouseButtonEventArgs"/> instance carrying mouse state information.
|
||||
/// The information carried by this instance is only valid within this method body.
|
||||
/// </param>
|
||||
protected virtual void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
MouseDown(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="MouseUp"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
/// A <see cref="MouseButtonEventArgs"/> instance carrying mouse state information.
|
||||
/// The information carried by this instance is only valid within this method body.
|
||||
/// </param>
|
||||
protected virtual void OnMouseUp(MouseButtonEventArgs e)
|
||||
{
|
||||
MouseUp(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="MouseMove"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
/// A <see cref="MouseMoveEventArgs"/> instance carrying mouse state information.
|
||||
/// The information carried by this instance is only valid within this method body.
|
||||
/// </param>
|
||||
protected virtual void OnMouseMove(MouseMoveEventArgs e)
|
||||
{
|
||||
MouseMove(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="MouseWheel"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
/// A <see cref="MouseWheelEventArgs"/> instance carrying mouse state information.
|
||||
/// The information carried by this instance is only valid within this method body.
|
||||
/// </param>
|
||||
protected virtual void OnMouseWheel(MouseWheelEventArgs e)
|
||||
{
|
||||
MouseWheel(this, e);
|
||||
}
|
||||
|
||||
#region OnResize
|
||||
|
||||
/// <summary>
|
||||
|
@ -1054,6 +1117,11 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
private void OnMouseDownInternal(object sender, MouseButtonEventArgs e) { OnMouseDown(e); }
|
||||
private void OnMouseUpInternal(object sender, MouseButtonEventArgs e) { OnMouseUp(e); }
|
||||
private void OnMouseMoveInternal(object sender, MouseMoveEventArgs e) { OnMouseMove(e); }
|
||||
private void OnMouseWheelInternal(object sender, MouseWheelEventArgs e) { OnMouseWheel(e); }
|
||||
|
||||
#region OnMoveInternal
|
||||
|
||||
private void OnMoveInternal(object sender, EventArgs e) { OnMove(e); }
|
||||
|
@ -1116,6 +1184,10 @@ namespace OpenTK
|
|||
implementation.KeyUp += OnKeyUpInternal;
|
||||
implementation.MouseEnter += OnMouseEnterInternal;
|
||||
implementation.MouseLeave += OnMouseLeaveInternal;
|
||||
implementation.MouseDown += OnMouseDownInternal;
|
||||
implementation.MouseUp += OnMouseUpInternal;
|
||||
implementation.MouseMove += OnMouseMoveInternal;
|
||||
implementation.MouseWheel += OnMouseWheelInternal;
|
||||
implementation.Move += OnMoveInternal;
|
||||
implementation.Resize += OnResizeInternal;
|
||||
implementation.TitleChanged += OnTitleChangedInternal;
|
||||
|
@ -1136,6 +1208,10 @@ namespace OpenTK
|
|||
implementation.KeyUp -= OnKeyUpInternal;
|
||||
implementation.MouseEnter -= OnMouseEnterInternal;
|
||||
implementation.MouseLeave -= OnMouseLeaveInternal;
|
||||
implementation.MouseDown -= OnMouseDownInternal;
|
||||
implementation.MouseUp -= OnMouseUpInternal;
|
||||
implementation.MouseMove -= OnMouseMoveInternal;
|
||||
implementation.MouseWheel -= OnMouseWheelInternal;
|
||||
implementation.Move -= OnMoveInternal;
|
||||
implementation.Resize -= OnResizeInternal;
|
||||
implementation.TitleChanged -= OnTitleChangedInternal;
|
||||
|
|
|
@ -366,9 +366,6 @@
|
|||
<Compile Include="Platform\X11\Structs.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Platform\X11\X11Input.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Platform\X11\X11Factory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -797,6 +794,9 @@
|
|||
<Compile Include="Platform\MacOS\Carbon\Cgl.cs" />
|
||||
<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>
|
||||
|
|
|
@ -42,18 +42,33 @@ namespace OpenTK.Platform
|
|||
|
||||
readonly LegacyJoystickDriver JoystickDriver = new LegacyJoystickDriver();
|
||||
|
||||
internal LegacyInputDriver()
|
||||
internal LegacyInputDriver(INativeWindow window)
|
||||
{
|
||||
dummy_mice_list.Add(new MouseDevice());
|
||||
Mouse[0].Description = "Standard Mouse";
|
||||
Mouse[0].NumberOfButtons = 3;
|
||||
Mouse[0].NumberOfWheels = 1;
|
||||
if (window == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
dummy_keyboard_list.Add(new KeyboardDevice());
|
||||
Keyboard[0].Description = "Standard Keyboard";
|
||||
Keyboard[0].NumberOfKeys = 101;
|
||||
Keyboard[0].NumberOfLeds = 3;
|
||||
Keyboard[0].NumberOfFunctionKeys = 12;
|
||||
var mouse = new MouseDevice();
|
||||
mouse.Description = "Standard Mouse";
|
||||
mouse.NumberOfButtons = 3;
|
||||
mouse.NumberOfWheels = 1;
|
||||
dummy_mice_list.Add(mouse);
|
||||
|
||||
var keyboard = new KeyboardDevice();
|
||||
keyboard.Description = "Standard Keyboard";
|
||||
keyboard.NumberOfKeys = 101;
|
||||
keyboard.NumberOfLeds = 3;
|
||||
keyboard.NumberOfFunctionKeys = 12;
|
||||
dummy_keyboard_list.Add(keyboard);
|
||||
|
||||
// Hook mouse events
|
||||
window.MouseDown += mouse.HandleMouseDown;
|
||||
window.MouseUp += mouse.HandleMouseUp;
|
||||
window.MouseMove += mouse.HandleMouseMove;
|
||||
window.MouseWheel += mouse.HandleMouseWheel;
|
||||
|
||||
// Hook keyboard events
|
||||
window.KeyDown += keyboard.HandleKeyDown;
|
||||
window.KeyUp += keyboard.HandleKeyUp;
|
||||
}
|
||||
|
||||
#region IInputDriver Members
|
||||
|
|
|
@ -29,7 +29,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenTK.Platform.MacOS.Carbon
|
||||
namespace OpenTK.Platform.MacOS
|
||||
{
|
||||
//
|
||||
// http://web.archive.org/web/20100501161453/http://www.classicteck.com/rbarticles/mackeyboard.php
|
||||
|
|
|
@ -35,6 +35,11 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
static class Class
|
||||
{
|
||||
public static readonly IntPtr NSAutoreleasePool = Get("NSAutoreleasePool");
|
||||
public static readonly IntPtr NSDictionary = Get("NSDictionary");
|
||||
public static readonly IntPtr NSNumber = Get("NSNumber");
|
||||
public static readonly IntPtr NSUserDefaults = Get("NSUserDefaults");
|
||||
|
||||
[DllImport (Cocoa.LibObjC)]
|
||||
extern static IntPtr class_getName(IntPtr handle);
|
||||
|
||||
|
|
|
@ -57,9 +57,15 @@ namespace OpenTK.Platform.MacOS
|
|||
[DllImport(LibObjC, EntryPoint="objc_msgSend")]
|
||||
public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1, IntPtr intPtr2, IntPtr intPtr3);
|
||||
|
||||
[DllImport(LibObjC, EntryPoint="objc_msgSend")]
|
||||
public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr intPtr1, IntPtr intPtr2, IntPtr intPtr3, IntPtr intPtr4, IntPtr intPtr5);
|
||||
|
||||
[DllImport(LibObjC, EntryPoint="objc_msgSend")]
|
||||
public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, IntPtr p1, PointF p2);
|
||||
|
||||
[DllImport(LibObjC, EntryPoint="objc_msgSend")]
|
||||
public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, bool p1);
|
||||
|
||||
[DllImport(LibObjC, EntryPoint="objc_msgSend")]
|
||||
public extern static IntPtr SendIntPtr(IntPtr receiver, IntPtr selector, SizeF p1);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace OpenTK.Platform.MacOS
|
|||
internal static void Initialize()
|
||||
{
|
||||
// Create the NSAutoreleasePool
|
||||
AutoreleasePool = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSAutoreleasePool"), Selector.Alloc), Selector.Init);
|
||||
AutoreleasePool = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.NSAutoreleasePool, Selector.Alloc), Selector.Init);
|
||||
|
||||
// Register a Quit method to be called on cmd-q
|
||||
IntPtr nsapp = Class.Get("NSApplication");
|
||||
|
@ -80,6 +80,23 @@ namespace OpenTK.Platform.MacOS
|
|||
|
||||
// Tell cocoa we're ready to run the application (usually called by [NSApp run]).
|
||||
Cocoa.SendVoid(Handle, Selector.Get("finishLaunching"));
|
||||
|
||||
// Disable momentum scrolling and long-press key pop-ups
|
||||
IntPtr settings = Cocoa.SendIntPtr(Class.NSDictionary, Selector.Alloc);
|
||||
IntPtr momentum_scrolling = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false);
|
||||
IntPtr press_and_hold = Cocoa.SendIntPtr(Class.NSNumber, Selector.Get("numberWithBool:"), false);
|
||||
|
||||
// Initialize and register the settings dictionary
|
||||
settings =
|
||||
Cocoa.SendIntPtr(settings, Selector.Get("initWithObjectsAndKeys:"),
|
||||
momentum_scrolling, Cocoa.ToNSString("AppleMomentumScrollSupported"),
|
||||
press_and_hold, Cocoa.ToNSString("ApplePressAndHoldEnabled"),
|
||||
IntPtr.Zero);
|
||||
Cocoa.SendVoid(
|
||||
Cocoa.SendIntPtr(Class.NSUserDefaults, Selector.Get("standardUserDefaults")),
|
||||
Selector.Get("registerDefaults:"),
|
||||
settings);
|
||||
Cocoa.SendVoid(settings, Selector.Release);
|
||||
}
|
||||
|
||||
internal static event EventHandler<CancelEventArgs> Quit = delegate { };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#region License
|
||||
#region License
|
||||
//
|
||||
// CocoaNativeWindow.cs
|
||||
//
|
||||
|
@ -38,30 +38,14 @@ using OpenTK.Input;
|
|||
|
||||
namespace OpenTK.Platform.MacOS
|
||||
{
|
||||
class CocoaNativeWindow : INativeWindow
|
||||
class CocoaNativeWindow : NativeWindowBase
|
||||
{
|
||||
static int UniqueId;
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
|
||||
static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:");
|
||||
static readonly IntPtr selSendEvent = Selector.Get("sendEvent:");
|
||||
//static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows");
|
||||
static readonly IntPtr selContentView = Selector.Get("contentView");
|
||||
static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:");
|
||||
static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:");
|
||||
static readonly IntPtr selPerformClose = Selector.Get("performClose:");
|
||||
|
@ -94,7 +78,10 @@ namespace OpenTK.Platform.MacOS
|
|||
static readonly IntPtr selLocationInWindowOwner = Selector.Get("locationInWindow");
|
||||
static readonly IntPtr selHide = Selector.Get("hide");
|
||||
static readonly IntPtr selUnhide = Selector.Get("unhide");
|
||||
static readonly IntPtr selScrollingDeltaX = Selector.Get("scrollingDeltaX");
|
||||
static readonly IntPtr selScrollingDeltaY = Selector.Get("scrollingDeltaY");
|
||||
static readonly IntPtr selDeltaX = Selector.Get("deltaX");
|
||||
static readonly IntPtr selDeltaY = Selector.Get("deltaY");
|
||||
static readonly IntPtr selButtonNumber = Selector.Get("buttonNumber");
|
||||
static readonly IntPtr selSetStyleMask = Selector.Get("setStyleMask:");
|
||||
static readonly IntPtr selStyleMask = Selector.Get("styleMask");
|
||||
|
@ -145,13 +132,10 @@ namespace OpenTK.Platform.MacOS
|
|||
private bool exists;
|
||||
private bool cursorVisible = true;
|
||||
private System.Drawing.Icon icon;
|
||||
private LegacyInputDriver inputDriver = new LegacyInputDriver();
|
||||
private WindowBorder windowBorder = WindowBorder.Resizable;
|
||||
private Nullable<WindowBorder> deferredWindowBorder;
|
||||
private Nullable<WindowBorder> previousWindowBorder;
|
||||
private WindowState windowState = WindowState.Normal;
|
||||
private OpenTK.Input.KeyboardKeyEventArgs keyArgs = new OpenTK.Input.KeyboardKeyEventArgs();
|
||||
private KeyPressEventArgs keyPressArgs = new KeyPressEventArgs((char)0);
|
||||
private string title;
|
||||
private RectangleF previousBounds;
|
||||
private int normalLevel;
|
||||
|
@ -160,7 +144,7 @@ namespace OpenTK.Platform.MacOS
|
|||
private bool cursorInsideWindow = true;
|
||||
private MouseCursor selectedCursor = MouseCursor.Default; // user-selected cursor
|
||||
|
||||
private const float scrollFactor = 120.0f;
|
||||
private const float scrollFactor = 10.0f;
|
||||
private const bool exclusiveFullscreen = false;
|
||||
|
||||
public CocoaNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
|
||||
|
@ -188,7 +172,17 @@ namespace OpenTK.Platform.MacOS
|
|||
Class.RegisterClass(viewClass);
|
||||
|
||||
// Create window instance
|
||||
var contentRect = new System.Drawing.RectangleF(x, y, width, height);
|
||||
// Note: The coordinate system of Cocoa places (0,0) at the bottom left.
|
||||
// We need to get the height of the main screen and flip that in order
|
||||
// to place the window at the correct position.
|
||||
// Note: NSWindows are laid out relative to the main screen.
|
||||
var screenRect =
|
||||
Cocoa.SendRect(
|
||||
Cocoa.SendIntPtr(
|
||||
Cocoa.SendIntPtr(Class.Get("NSScreen"), Selector.Get("screens")),
|
||||
Selector.Get("objectAtIndex:"), 0),
|
||||
Selector.Get("frame"));
|
||||
var contentRect = new System.Drawing.RectangleF(x, screenRect.Height - height - y, width, height);
|
||||
var style = GetStyleMask(windowBorder);
|
||||
var bufferingType = NSBackingStore.Buffered;
|
||||
|
||||
|
@ -259,7 +253,7 @@ namespace OpenTK.Platform.MacOS
|
|||
GraphicsContext.CurrentContext.Update(windowInfo);
|
||||
|
||||
if (suppressResize == 0)
|
||||
Resize(this, EventArgs.Empty);
|
||||
OnResize(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void ApplicationQuit(object sender, CancelEventArgs e)
|
||||
|
@ -272,17 +266,17 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
// Problem: Called only when you stop moving for a brief moment,
|
||||
// not each frame as it is on PC.
|
||||
Move(this, EventArgs.Empty);
|
||||
OnMove(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void WindowDidBecomeKey(IntPtr self, IntPtr cmd, IntPtr notification)
|
||||
{
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
OnFocusedChanged(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void WindowDidResignKey(IntPtr self, IntPtr cmd, IntPtr notification)
|
||||
{
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
OnFocusedChanged(EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void WindowWillMiniaturize(IntPtr self, IntPtr cmd, IntPtr notification)
|
||||
|
@ -296,14 +290,14 @@ namespace OpenTK.Platform.MacOS
|
|||
private void WindowDidMiniaturize(IntPtr self, IntPtr cmd, IntPtr notification)
|
||||
{
|
||||
windowState = WindowState.Minimized;
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
OnResize(false); // Don't set tracking area when we minimize
|
||||
}
|
||||
|
||||
private void WindowDidDeminiaturize(IntPtr self, IntPtr cmd, IntPtr notification)
|
||||
{
|
||||
windowState = WindowState.Normal;
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
OnResize(true);
|
||||
}
|
||||
|
||||
|
@ -321,7 +315,7 @@ namespace OpenTK.Platform.MacOS
|
|||
InternalBounds = toFrame;
|
||||
windowState = WindowState.Maximized;
|
||||
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -329,11 +323,11 @@ namespace OpenTK.Platform.MacOS
|
|||
private bool WindowShouldClose(IntPtr self, IntPtr cmd, IntPtr sender)
|
||||
{
|
||||
var cancelArgs = new CancelEventArgs();
|
||||
Closing(this, cancelArgs);
|
||||
OnClosing(cancelArgs);
|
||||
|
||||
if (!cancelArgs.Cancel)
|
||||
{
|
||||
Closed(this, EventArgs.Empty);
|
||||
OnClosed(EventArgs.Empty);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -377,7 +371,7 @@ namespace OpenTK.Platform.MacOS
|
|||
Cocoa.SendVoid(owner, selAddTrackingArea, trackingArea);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
public override void Close()
|
||||
{
|
||||
shouldClose = true;
|
||||
}
|
||||
|
@ -391,13 +385,6 @@ namespace OpenTK.Platform.MacOS
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
private void GetKey(ushort keyCode, NSEventModifierMask modifierFlags, OpenTK.Input.KeyboardKeyEventArgs args)
|
||||
{
|
||||
args.Key = MacOSKeyMap.GetKey((Carbon.MacOSKeyCode)keyCode);
|
||||
args.Modifiers = GetModifiers(modifierFlags);
|
||||
args.ScanCode = (uint)keyCode;
|
||||
}
|
||||
|
||||
private MouseButton GetMouseButton(int cocoaButtonIndex)
|
||||
{
|
||||
if (cocoaButtonIndex == 0) return MouseButton.Left;
|
||||
|
@ -409,8 +396,10 @@ namespace OpenTK.Platform.MacOS
|
|||
return (MouseButton)cocoaButtonIndex;
|
||||
}
|
||||
|
||||
public void ProcessEvents()
|
||||
public override void ProcessEvents()
|
||||
{
|
||||
base.ProcessEvents();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var e = Cocoa.SendIntPtr(NSApplication.Handle, selNextEventMatchingMask, uint.MaxValue, IntPtr.Zero, NSDefaultRunLoopMode, true);
|
||||
|
@ -423,16 +412,11 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
case NSEventType.KeyDown:
|
||||
{
|
||||
var keyCode = Cocoa.SendUshort(e, selKeyCode);
|
||||
var modifierFlags = (NSEventModifierMask)Cocoa.SendUint(e, selModifierFlags);
|
||||
MacOSKeyCode keyCode = (MacOSKeyCode)Cocoa.SendUshort(e, selKeyCode);
|
||||
var isARepeat = Cocoa.SendBool(e, selIsARepeat);
|
||||
GetKey(keyCode, modifierFlags, keyArgs);
|
||||
InputDriver.Keyboard[0].SetKey(keyArgs.Key, keyArgs.ScanCode, true);
|
||||
Key key = MacOSKeyMap.GetKey(keyCode);
|
||||
|
||||
if (!isARepeat || InputDriver.Keyboard[0].KeyRepeat)
|
||||
{
|
||||
KeyDown(this, keyArgs);
|
||||
}
|
||||
OnKeyDown(key, isARepeat);
|
||||
|
||||
var s = Cocoa.FromNSString(Cocoa.SendIntPtr(e, selCharactersIgnoringModifiers));
|
||||
foreach (var c in s)
|
||||
|
@ -440,10 +424,9 @@ namespace OpenTK.Platform.MacOS
|
|||
int intVal = (int)c;
|
||||
if (!Char.IsControl(c) && (intVal < 63232 || intVal > 63235))
|
||||
{
|
||||
// For some reason, arrow keys (mapped 63232-63235) are seen as non-control characters, so get rid of those.
|
||||
|
||||
keyPressArgs.KeyChar = c;
|
||||
KeyPress(this, keyPressArgs);
|
||||
// For some reason, arrow keys (mapped 63232-63235)
|
||||
// are seen as non-control characters, so get rid of those.
|
||||
OnKeyPress(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -451,13 +434,16 @@ namespace OpenTK.Platform.MacOS
|
|||
|
||||
case NSEventType.KeyUp:
|
||||
{
|
||||
var keyCode = Cocoa.SendUshort(e, selKeyCode);
|
||||
MacOSKeyCode keyCode = (MacOSKeyCode)Cocoa.SendUshort(e, selKeyCode);
|
||||
Key key = MacOSKeyMap.GetKey(keyCode);
|
||||
OnKeyUp(key);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSEventType.FlagsChanged:
|
||||
{
|
||||
var modifierFlags = (NSEventModifierMask)Cocoa.SendUint(e, selModifierFlags);
|
||||
|
||||
GetKey(keyCode, modifierFlags, keyArgs);
|
||||
InputDriver.Keyboard[0].SetKey(keyArgs.Key, keyArgs.ScanCode, false);
|
||||
|
||||
KeyUp(this, keyArgs);
|
||||
UpdateModifierFlags(GetModifiers(modifierFlags));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -472,8 +458,7 @@ namespace OpenTK.Platform.MacOS
|
|||
//SetCursor(selectedCursor);
|
||||
}
|
||||
|
||||
cursorInsideWindow = true;
|
||||
MouseEnter(this, EventArgs.Empty);
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -486,11 +471,10 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
if (selectedCursor != MouseCursor.Default)
|
||||
{
|
||||
SetCursor(MouseCursor.Default);
|
||||
//SetCursor(MouseCursor.Default);
|
||||
}
|
||||
|
||||
cursorInsideWindow = false;
|
||||
MouseLeave(this, EventArgs.Empty);
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -500,18 +484,38 @@ namespace OpenTK.Platform.MacOS
|
|||
case NSEventType.OtherMouseDragged:
|
||||
case NSEventType.MouseMoved:
|
||||
{
|
||||
var pf = Cocoa.SendPoint(e, selLocationInWindowOwner);
|
||||
Point p = new Point(MouseState.X, MouseState.Y);
|
||||
if (CursorVisible)
|
||||
{
|
||||
// Use absolute coordinates
|
||||
var pf = Cocoa.SendPoint(e, selLocationInWindowOwner);
|
||||
|
||||
// Convert from points to pixel coordinates
|
||||
var rf = Cocoa.SendRect(windowInfo.Handle, selConvertRectToBacking,
|
||||
new RectangleF(pf.X, pf.Y, 0, 0));
|
||||
// Convert from points to pixel coordinates
|
||||
var rf = Cocoa.SendRect(windowInfo.Handle, selConvertRectToBacking,
|
||||
new RectangleF(pf.X, pf.Y, 0, 0));
|
||||
|
||||
// See CocoaDrawingGuide under "Converting from Window to View Coordinates"
|
||||
var p = new Point(
|
||||
MathHelper.Clamp((int)Math.Round(rf.X), 0, Width),
|
||||
MathHelper.Clamp((int)Math.Round(Height - rf.Y), 0, Height));
|
||||
// See CocoaDrawingGuide under "Converting from Window to View Coordinates"
|
||||
p = new Point(
|
||||
MathHelper.Clamp((int)Math.Round(rf.X), 0, Width),
|
||||
MathHelper.Clamp((int)Math.Round(Height - rf.Y), 0, Height));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mouse has been disassociated,
|
||||
// use relative coordinates
|
||||
var dx = Cocoa.SendFloat(e, selDeltaX);
|
||||
var dy = Cocoa.SendFloat(e, selDeltaY);
|
||||
|
||||
InputDriver.Mouse[0].Position = p;
|
||||
p = new Point(
|
||||
MathHelper.Clamp((int)Math.Round(p.X + dx), 0, Width),
|
||||
MathHelper.Clamp((int)Math.Round(p.Y + dy), 0, Height));
|
||||
}
|
||||
|
||||
// Only raise events when the mouse has actually moved
|
||||
if (MouseState.X != p.X || MouseState.Y != p.Y)
|
||||
{
|
||||
OnMouseMove(p.X, p.Y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -520,15 +524,23 @@ namespace OpenTK.Platform.MacOS
|
|||
|
||||
case NSEventType.ScrollWheel:
|
||||
{
|
||||
var scrollingDelta = Cocoa.SendFloat(e, selScrollingDeltaY);
|
||||
var factor = 1.0f;
|
||||
|
||||
float dx, dy;
|
||||
if (Cocoa.SendBool(e, selHasPreciseScrollingDeltas))
|
||||
{
|
||||
factor = 1.0f / scrollFactor; // Problem: Don't know what factor to use here, but this seems to work.
|
||||
dx = Cocoa.SendFloat(e, selScrollingDeltaX) / scrollFactor;
|
||||
dy = Cocoa.SendFloat(e, selScrollingDeltaY) / scrollFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = Cocoa.SendFloat(e, selDeltaX);
|
||||
dy = Cocoa.SendFloat(e, selDeltaY);
|
||||
}
|
||||
|
||||
InputDriver.Mouse[0].WheelPrecise += scrollingDelta * factor;
|
||||
// Only raise wheel events when the user has actually scrolled
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
OnMouseWheel(dx, dy);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -537,7 +549,7 @@ namespace OpenTK.Platform.MacOS
|
|||
case NSEventType.OtherMouseDown:
|
||||
{
|
||||
var buttonNumber = Cocoa.SendInt(e, selButtonNumber);
|
||||
InputDriver.Mouse[0][GetMouseButton(buttonNumber)] = true;
|
||||
OnMouseDown(GetMouseButton(buttonNumber));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -546,7 +558,7 @@ namespace OpenTK.Platform.MacOS
|
|||
case NSEventType.OtherMouseUp:
|
||||
{
|
||||
var buttonNumber = Cocoa.SendInt(e, selButtonNumber);
|
||||
InputDriver.Mouse[0][GetMouseButton(buttonNumber)] = false;
|
||||
OnMouseUp(GetMouseButton(buttonNumber));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -575,19 +587,25 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Point PointToClient(System.Drawing.Point point)
|
||||
public override System.Drawing.Point PointToClient(System.Drawing.Point point)
|
||||
{
|
||||
var r = Cocoa.SendRect(windowInfo.Handle, selConvertRectFromScreen, new RectangleF(point.X, point.Y, 0, 0));
|
||||
return new Point((int)r.X, (int)(GetContentViewFrame().Height - GetCurrentScreenFrame().Height - r.Y));
|
||||
var r =
|
||||
Cocoa.SendRect(windowInfo.ViewHandle, selConvertRectToBacking,
|
||||
Cocoa.SendRect(windowInfo.Handle, selConvertRectFromScreen,
|
||||
new RectangleF(point.X, GetCurrentScreenFrame().Height - point.Y, 0, 0)));
|
||||
return new Point((int)r.X, (int)(Height - r.Y));
|
||||
}
|
||||
|
||||
public System.Drawing.Point PointToScreen(System.Drawing.Point point)
|
||||
public override System.Drawing.Point PointToScreen(System.Drawing.Point point)
|
||||
{
|
||||
var r = Cocoa.SendRect(windowInfo.Handle, selConvertRectToScreen, new RectangleF(point.X, point.Y, 0, 0));
|
||||
return new Point((int)r.X, (int)(-GetContentViewFrame().Height + GetCurrentScreenFrame().Height - r.Y));
|
||||
var r =
|
||||
Cocoa.SendRect(windowInfo.Handle, selConvertRectToScreen,
|
||||
Cocoa.SendRect(windowInfo.ViewHandle, selConvertRectFromBacking,
|
||||
new RectangleF(point.X, Height - point.Y, 0, 0)));
|
||||
return new Point((int)r.X, (int)(GetCurrentScreenFrame().Height - r.Y));
|
||||
}
|
||||
|
||||
public System.Drawing.Icon Icon
|
||||
public override System.Drawing.Icon Icon
|
||||
{
|
||||
get { return icon; }
|
||||
set
|
||||
|
@ -598,11 +616,11 @@ namespace OpenTK.Platform.MacOS
|
|||
IntPtr nsimg = Cocoa.ToNSImage(img);
|
||||
Cocoa.SendVoid(NSApplication.Handle, selSetApplicationIconImage, nsimg);
|
||||
}
|
||||
IconChanged(this, EventArgs.Empty);
|
||||
OnIconChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
public override string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -614,7 +632,7 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public bool Focused
|
||||
public override bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -622,7 +640,7 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -631,11 +649,11 @@ namespace OpenTK.Platform.MacOS
|
|||
set
|
||||
{
|
||||
Cocoa.SendVoid(windowInfo.Handle, selSetIsVisible, value);
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
OnVisibleChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists
|
||||
public override bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -643,7 +661,7 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public IWindowInfo WindowInfo
|
||||
public override IWindowInfo WindowInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -702,7 +720,7 @@ namespace OpenTK.Platform.MacOS
|
|||
previousWindowBorder = null;
|
||||
}
|
||||
|
||||
public WindowState WindowState
|
||||
public override WindowState WindowState
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -735,7 +753,7 @@ namespace OpenTK.Platform.MacOS
|
|||
InternalBounds = GetCurrentScreenFrame();
|
||||
|
||||
windowState = value;
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
}
|
||||
else if (value == WindowState.Maximized)
|
||||
{
|
||||
|
@ -748,13 +766,13 @@ namespace OpenTK.Platform.MacOS
|
|||
else if (value == WindowState.Normal)
|
||||
{
|
||||
windowState = value;
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
Resize(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
OnResize(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WindowBorder WindowBorder
|
||||
public override WindowBorder WindowBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -773,7 +791,7 @@ namespace OpenTK.Platform.MacOS
|
|||
return;
|
||||
|
||||
SetWindowBorder(value);
|
||||
WindowBorderChanged(this, EventArgs.Empty);
|
||||
OnWindowBorderChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,16 +813,26 @@ namespace OpenTK.Platform.MacOS
|
|||
return (NSWindowStyle)0;
|
||||
}
|
||||
|
||||
public System.Drawing.Rectangle Bounds
|
||||
public override System.Drawing.Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = Cocoa.SendRect(windowInfo.Handle, selFrame);
|
||||
return new Rectangle((int)r.X, (int)(GetCurrentScreenFrame().Height - r.Y), (int)r.Width, (int)r.Height);
|
||||
return new Rectangle(
|
||||
(int)r.X,
|
||||
(int)(GetCurrentScreenFrame().Height - r.Y - r.Height),
|
||||
(int)r.Width,
|
||||
(int)r.Height);
|
||||
}
|
||||
set
|
||||
{
|
||||
Cocoa.SendVoid(windowInfo.Handle, selSetFrame, new RectangleF(value.X, GetCurrentScreenFrame().Height - value.Y, value.Width, value.Height), true);
|
||||
Cocoa.SendVoid(windowInfo.Handle, selSetFrame,
|
||||
new RectangleF(
|
||||
value.X,
|
||||
GetCurrentScreenFrame().Height - value.Y - value.Height,
|
||||
value.Width,
|
||||
value.Height),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -820,105 +848,13 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Point Location
|
||||
public override System.Drawing.Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Location;
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = Bounds;
|
||||
b.Location = value;
|
||||
Bounds = b;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Size Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = Bounds;
|
||||
b.Y -= Bounds.Height;
|
||||
b.Y += value.Height;
|
||||
b.Size = value;
|
||||
Bounds = b;
|
||||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.X;
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = Bounds;
|
||||
b.X = value;
|
||||
Bounds = b;
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
var b = Bounds;
|
||||
b.Y = value;
|
||||
Bounds = b;
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return ClientRectangle.Width; }
|
||||
set
|
||||
{
|
||||
var s = ClientSize;
|
||||
s.Width = value;
|
||||
ClientSize = s;
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return ClientRectangle.Height; }
|
||||
set
|
||||
{
|
||||
var s = ClientSize;
|
||||
s.Height = value;
|
||||
ClientSize = s;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Rectangle ClientRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
var contentViewBounds = Cocoa.SendRect(windowInfo.ViewHandle, selBounds);
|
||||
var bounds = Cocoa.SendRect(windowInfo.Handle, selConvertRectToBacking, contentViewBounds);
|
||||
return new Rectangle((int)bounds.X, (int)bounds.Y, (int)bounds.Width, (int)bounds.Height);
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientSize = value.Size; // Just set size, to be consistent with WinGLNative.
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientRectangle.Size;
|
||||
return new Size((int)bounds.Width, (int)bounds.Height);
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -928,15 +864,7 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public OpenTK.Input.IInputDriver InputDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
return inputDriver;
|
||||
}
|
||||
}
|
||||
|
||||
public MouseCursor Cursor
|
||||
public override MouseCursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1058,7 +986,7 @@ namespace OpenTK.Platform.MacOS
|
|||
Cocoa.SendVoid(windowInfo.Handle, selInvalidateCursorRectsForView, windowInfo.ViewHandle);
|
||||
}
|
||||
|
||||
public bool CursorVisible
|
||||
public override bool CursorVisible
|
||||
{
|
||||
get { return cursorVisible; }
|
||||
set
|
||||
|
@ -1075,13 +1003,7 @@ namespace OpenTK.Platform.MacOS
|
|||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
@ -1105,12 +1027,12 @@ namespace OpenTK.Platform.MacOS
|
|||
Cocoa.SendVoid(windowInfo.Handle, Selector.Release);
|
||||
}
|
||||
|
||||
Disposed(this, EventArgs.Empty);
|
||||
OnDisposed(EventArgs.Empty);
|
||||
}
|
||||
|
||||
~CocoaNativeWindow()
|
||||
public static IntPtr GetView(IntPtr windowHandle)
|
||||
{
|
||||
Dispose(false);
|
||||
return Cocoa.SendIntPtr(windowHandle, selContentView);
|
||||
}
|
||||
|
||||
private RectangleF GetContentViewFrame()
|
||||
|
@ -1135,25 +1057,27 @@ namespace OpenTK.Platform.MacOS
|
|||
|
||||
private void SetCursorVisible(bool visible)
|
||||
{
|
||||
// If the mouse is outside the window and we want to hide it,
|
||||
// move it inside the window first.
|
||||
// Otherwise, if we are making the cursor visible again,
|
||||
// we place it in the same spot as reported in the current
|
||||
// MouseState to avoid sudden jumps.
|
||||
if (!visible && !Bounds.Contains(new Point(MouseState.X, MouseState.Y)))
|
||||
{
|
||||
Mouse.SetPosition(
|
||||
(Bounds.Left + Bounds.Right) / 2,
|
||||
(Bounds.Top + Bounds.Bottom) / 2);
|
||||
}
|
||||
else if (visible)
|
||||
{
|
||||
var p = PointToScreen(new Point(MouseState.X, MouseState.Y));
|
||||
Mouse.SetPosition((int)p.X, (int)p.Y);
|
||||
}
|
||||
|
||||
Carbon.CG.AssociateMouseAndMouseCursorPosition(visible);
|
||||
Cocoa.SendVoid(NSCursor, visible ? selUnhide : selHide);
|
||||
}
|
||||
|
||||
private void SetCursor(MouseCursor cursor)
|
||||
{
|
||||
if (cursor == MouseCursor.Default)
|
||||
{
|
||||
Cocoa.SendVoid(NSCursor, selUnhide);
|
||||
}
|
||||
else if (cursor == MouseCursor.Empty)
|
||||
{
|
||||
Cocoa.SendVoid(NSCursor, selHide);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void SetMenuVisible(bool visible)
|
||||
{
|
||||
var options = (NSApplicationPresentationOptions)Cocoa.SendInt(NSApplication.Handle, selPresentationOptions);
|
||||
|
@ -1178,7 +1102,7 @@ namespace OpenTK.Platform.MacOS
|
|||
Cocoa.SendIntPtr(windowInfo.Handle, selSetTitle, Cocoa.ToNSString(title));
|
||||
if (callEvent)
|
||||
{
|
||||
TitleChanged(this, EventArgs.Empty);
|
||||
OnTitleChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -324,7 +324,7 @@ namespace OpenTK.Platform.MacOS
|
|||
break;
|
||||
|
||||
case HIDUsageGD.Wheel:
|
||||
mouse.State.WheelPrecise += v_int;
|
||||
mouse.State.SetScrollRelative(0, v_int);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -332,6 +332,15 @@ namespace OpenTK.Platform.MacOS
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +390,8 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
Debug.Print("[Warning] Key {0} not mapped.", usage);
|
||||
}
|
||||
keyboard.State.SetKeyState(RawKeyMap[usage], (byte)usage, v_int != 0);
|
||||
|
||||
keyboard.State[RawKeyMap[usage]] = v_int != 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1107,6 +1117,12 @@ namespace OpenTK.Platform.MacOS
|
|||
VendorDefinedStart = 0xFF00
|
||||
}
|
||||
|
||||
// Consumer electronic devices
|
||||
enum HIDUsageCD
|
||||
{
|
||||
ACPan = 0x0238
|
||||
}
|
||||
|
||||
// Generic desktop usage
|
||||
enum HIDUsageGD
|
||||
{
|
||||
|
|
477
Source/OpenTK/Platform/NativeWindowBase.cs
Normal file
477
Source/OpenTK/Platform/NativeWindowBase.cs
Normal file
|
@ -0,0 +1,477 @@
|
|||
#region License
|
||||
//
|
||||
// NativeWindowBase.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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform
|
||||
{
|
||||
// Common base class for all INativeWindow implementations
|
||||
abstract class NativeWindowBase : INativeWindow
|
||||
{
|
||||
readonly LegacyInputDriver LegacyInputDriver;
|
||||
|
||||
readonly MouseButtonEventArgs MouseDownArgs = new MouseButtonEventArgs();
|
||||
readonly MouseButtonEventArgs MouseUpArgs = new MouseButtonEventArgs();
|
||||
readonly MouseMoveEventArgs MouseMoveArgs = new MouseMoveEventArgs();
|
||||
readonly MouseWheelEventArgs MouseWheelArgs = new MouseWheelEventArgs();
|
||||
|
||||
readonly KeyboardKeyEventArgs KeyDownArgs = new KeyboardKeyEventArgs();
|
||||
readonly KeyboardKeyEventArgs KeyUpArgs = new KeyboardKeyEventArgs();
|
||||
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();
|
||||
protected KeyboardState KeyboardState = new KeyboardState();
|
||||
|
||||
MouseState PreviousMouseState = new MouseState();
|
||||
|
||||
internal NativeWindowBase()
|
||||
{
|
||||
LegacyInputDriver = new LegacyInputDriver(this);
|
||||
MouseState.SetIsConnected(true);
|
||||
KeyboardState.SetIsConnected(true);
|
||||
PreviousMouseState.SetIsConnected(true);
|
||||
}
|
||||
|
||||
#region Protected Members
|
||||
|
||||
protected void OnMove(EventArgs e)
|
||||
{
|
||||
Move(this, e);
|
||||
}
|
||||
|
||||
protected void OnResize(EventArgs e)
|
||||
{
|
||||
Resize(this, e);
|
||||
}
|
||||
|
||||
protected void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
Closing(this, e);
|
||||
}
|
||||
|
||||
protected void OnClosed(EventArgs e)
|
||||
{
|
||||
Closed(this, e);
|
||||
}
|
||||
|
||||
protected void OnDisposed(EventArgs e)
|
||||
{
|
||||
Disposed(this, e);
|
||||
}
|
||||
|
||||
protected void OnIconChanged(EventArgs e)
|
||||
{
|
||||
IconChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnTitleChanged(EventArgs e)
|
||||
{
|
||||
TitleChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnVisibleChanged(EventArgs e)
|
||||
{
|
||||
VisibleChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnFocusedChanged(EventArgs e)
|
||||
{
|
||||
FocusedChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnWindowBorderChanged(EventArgs e)
|
||||
{
|
||||
WindowBorderChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnWindowStateChanged(EventArgs e)
|
||||
{
|
||||
WindowStateChanged(this, e);
|
||||
}
|
||||
|
||||
protected void OnKeyDown(Key key, bool repeat)
|
||||
{
|
||||
KeyboardState.SetKeyState(key, true);
|
||||
|
||||
var e = KeyDownArgs;
|
||||
e.Keyboard = KeyboardState;
|
||||
e.Key = key;
|
||||
e.IsRepeat = repeat;
|
||||
KeyDown(this, e);
|
||||
}
|
||||
|
||||
protected void OnKeyPress(char c)
|
||||
{
|
||||
var e = KeyPressArgs;
|
||||
e.KeyChar = c;
|
||||
KeyPress(this, e);
|
||||
}
|
||||
|
||||
protected void OnKeyUp(Key key)
|
||||
{
|
||||
KeyboardState.SetKeyState(key, false);
|
||||
|
||||
var e = KeyUpArgs;
|
||||
e.Keyboard = KeyboardState;
|
||||
e.Key = key;
|
||||
e.IsRepeat = false;
|
||||
KeyUp(this, e);
|
||||
}
|
||||
|
||||
/// \internal
|
||||
/// <summary>
|
||||
/// Call this method to simulate KeyDown/KeyUp events
|
||||
/// on platforms that do not generate key events for
|
||||
/// modifier flags (e.g. Mac/Cocoa).
|
||||
/// Note: this method does not distinguish between the
|
||||
/// left and right variants of modifier keys.
|
||||
/// </summary>
|
||||
/// <param name="mods">Mods.</param>
|
||||
protected void UpdateModifierFlags(KeyModifiers mods)
|
||||
{
|
||||
bool alt = (mods & KeyModifiers.Alt) != 0;
|
||||
bool control = (mods & KeyModifiers.Control) != 0;
|
||||
bool shift = (mods & KeyModifiers.Shift) != 0;
|
||||
|
||||
if (alt)
|
||||
{
|
||||
OnKeyDown(Key.AltLeft, KeyboardState[Key.AltLeft]);
|
||||
OnKeyDown(Key.AltRight, KeyboardState[Key.AltLeft]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KeyboardState[Key.AltLeft])
|
||||
{
|
||||
OnKeyUp(Key.AltLeft);
|
||||
}
|
||||
if (KeyboardState[Key.AltRight])
|
||||
{
|
||||
OnKeyUp(Key.AltRight);
|
||||
}
|
||||
}
|
||||
|
||||
if (control)
|
||||
{
|
||||
OnKeyDown(Key.ControlLeft, KeyboardState[Key.AltLeft]);
|
||||
OnKeyDown(Key.ControlRight, KeyboardState[Key.AltLeft]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KeyboardState[Key.ControlLeft])
|
||||
{
|
||||
OnKeyUp(Key.ControlLeft);
|
||||
}
|
||||
if (KeyboardState[Key.ControlRight])
|
||||
{
|
||||
OnKeyUp(Key.ControlRight);
|
||||
}
|
||||
}
|
||||
|
||||
if (shift)
|
||||
{
|
||||
OnKeyDown(Key.ShiftLeft, KeyboardState[Key.AltLeft]);
|
||||
OnKeyDown(Key.ShiftRight, KeyboardState[Key.AltLeft]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KeyboardState[Key.ShiftLeft])
|
||||
{
|
||||
OnKeyUp(Key.ShiftLeft);
|
||||
}
|
||||
if (KeyboardState[Key.ShiftRight])
|
||||
{
|
||||
OnKeyUp(Key.ShiftRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
MouseLeave(this, e);
|
||||
}
|
||||
|
||||
protected void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
MouseEnter(this, e);
|
||||
}
|
||||
|
||||
protected void OnMouseDown(MouseButton button)
|
||||
{
|
||||
MouseState[button] = true;
|
||||
|
||||
var e = MouseDownArgs;
|
||||
e.Mouse = MouseState;
|
||||
|
||||
MouseDown(this, e);
|
||||
}
|
||||
|
||||
protected void OnMouseUp(MouseButton button)
|
||||
{
|
||||
MouseState[button] = false;
|
||||
|
||||
var e = MouseUpArgs;
|
||||
e.Mouse = MouseState;
|
||||
|
||||
MouseUp(this, e);
|
||||
}
|
||||
|
||||
protected void OnMouseMove(int x, int y)
|
||||
{
|
||||
MouseState.X = x;
|
||||
MouseState.Y = y;
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
PreviousMouseState = MouseState;
|
||||
MouseMove(this, e);
|
||||
}
|
||||
|
||||
protected void OnMouseWheel(float dx, float dy)
|
||||
{
|
||||
MouseState.SetScrollRelative(dx, dy);
|
||||
|
||||
var e = MouseWheelArgs;
|
||||
e.Mouse = MouseState;
|
||||
e.DeltaPrecise = MouseState.Scroll.Y - PreviousMouseState.Scroll.Y;
|
||||
|
||||
if (dx == 0 && dy == 0)
|
||||
{
|
||||
Debug.WriteLine("OnMouseWheel called without moving the mouse wheel.");
|
||||
return;
|
||||
}
|
||||
|
||||
PreviousMouseState = MouseState;
|
||||
MouseWheel(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INativeWindow Members
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
public event EventHandler<MouseButtonEventArgs> MouseDown = delegate { };
|
||||
public event EventHandler<MouseButtonEventArgs> MouseUp = delegate { };
|
||||
public event EventHandler<MouseMoveEventArgs> MouseMove = delegate { };
|
||||
public event EventHandler<MouseWheelEventArgs> MouseWheel = delegate { };
|
||||
|
||||
public abstract void Close();
|
||||
|
||||
public virtual void ProcessEvents()
|
||||
{
|
||||
if (!Focused)
|
||||
{
|
||||
// Clear keyboard state, otherwise KeyUp
|
||||
// events may be missed resulting in stuck
|
||||
// keys.
|
||||
for (Key key = 0; key < Key.LastKey; key++)
|
||||
{
|
||||
if (KeyboardState[key])
|
||||
{
|
||||
OnKeyUp(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Point PointToClient(Point point);
|
||||
|
||||
public abstract Point PointToScreen(Point point);
|
||||
|
||||
public abstract Icon Icon { get; set; }
|
||||
|
||||
public abstract string Title { get; set; }
|
||||
|
||||
public abstract bool Focused { get; }
|
||||
|
||||
public abstract bool Visible { get; set; }
|
||||
|
||||
public abstract bool Exists { get; }
|
||||
|
||||
public abstract IWindowInfo WindowInfo { get; }
|
||||
|
||||
public abstract WindowState WindowState { get; set; }
|
||||
|
||||
public abstract WindowBorder WindowBorder { get; set; }
|
||||
|
||||
public abstract Rectangle Bounds { get; set; }
|
||||
|
||||
public virtual Point Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Location;
|
||||
}
|
||||
set
|
||||
{
|
||||
Bounds = new Rectangle(value, Bounds.Size);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Size Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
Bounds = new Rectangle(Bounds.Location, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Rectangle old = Bounds;
|
||||
Bounds = new Rectangle(value, old.Y, old.Width, old.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return Bounds.Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Rectangle old = Bounds;
|
||||
Bounds = new Rectangle(old.X, value, old.Width, old.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientSize.Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
Rectangle old = ClientRectangle;
|
||||
ClientRectangle = new Rectangle(old.X, old.Y, value, old.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientSize.Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
Rectangle old = ClientRectangle;
|
||||
Bounds = new Rectangle(old.X, old.Y, old.Width, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle ClientRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Rectangle(Point.Empty, ClientSize);
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientSize = value.Size;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Size ClientSize { get; set; }
|
||||
|
||||
public virtual IInputDriver InputDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
return LegacyInputDriver;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool CursorVisible { get; set; }
|
||||
|
||||
public abstract MouseCursor Cursor { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected abstract void Dispose(bool disposing);
|
||||
|
||||
~NativeWindowBase()
|
||||
{
|
||||
Debug.Print("NativeWindowBase leaked, did you forget to call Dispose()?");
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -1572,8 +1572,8 @@ namespace OpenTK.Platform.SDL2
|
|||
public UInt32 Which;
|
||||
public Button Button;
|
||||
public State State;
|
||||
public byte Clicks;
|
||||
byte padding1;
|
||||
byte padding2;
|
||||
public Int32 X;
|
||||
public Int32 Y;
|
||||
}
|
||||
|
@ -1584,10 +1584,7 @@ namespace OpenTK.Platform.SDL2
|
|||
public uint Timestamp;
|
||||
public uint WindowID;
|
||||
public uint Which;
|
||||
public State State;
|
||||
byte padding1;
|
||||
byte padding2;
|
||||
byte padding3;
|
||||
public ButtonFlags State;
|
||||
public Int32 X;
|
||||
public Int32 Y;
|
||||
public Int32 Xrel;
|
||||
|
@ -1617,10 +1614,6 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
|
||||
public const uint TouchMouseID = 0xffffffff;
|
||||
|
||||
public static class GL
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
struct Rect
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
|
||||
{
|
||||
return new Sdl2NativeWindow(x, y, width, height, title, options, device, InputDriver);
|
||||
return new Sdl2NativeWindow(x, y, width, height, title, options, device);
|
||||
}
|
||||
|
||||
public override IDisplayDeviceDriver CreateDisplayDeviceDriver()
|
||||
|
|
|
@ -34,7 +34,7 @@ using OpenTK.Input;
|
|||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2InputDriver : IInputDriver2, IInputDriver
|
||||
class Sdl2InputDriver : IInputDriver2
|
||||
{
|
||||
readonly static Dictionary<IntPtr, Sdl2InputDriver> DriverHandles =
|
||||
new Dictionary<IntPtr, Sdl2InputDriver>();
|
||||
|
@ -154,51 +154,6 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver Members
|
||||
|
||||
public void Poll()
|
||||
{
|
||||
joystick_driver.Poll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IJoystickDriver Members
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get
|
||||
{
|
||||
return joystick_driver.Joysticks;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouseDriver Members
|
||||
|
||||
public IList<MouseDevice> Mouse
|
||||
{
|
||||
get
|
||||
{
|
||||
return mouse_driver.Mouse;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IKeyboardDriver Members
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get
|
||||
{
|
||||
return keyboard_driver.Keyboard;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver2 Members
|
||||
|
||||
public IMouseDriver2 MouseDriver
|
||||
|
|
|
@ -298,6 +298,15 @@ namespace OpenTK.Platform.SDL2
|
|||
return Key.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyModifiers GetModifiers(Keymod mod)
|
||||
{
|
||||
KeyModifiers result = 0;
|
||||
result |= (mod & Keymod.ALT) != 0 ? KeyModifiers.Alt : 0;
|
||||
result |= (mod & Keymod.CTRL) != 0 ? KeyModifiers.Control : 0;
|
||||
result |= (mod & Keymod.SHIFT) != 0 ? KeyModifiers.Shift : 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ using OpenTK.Input;
|
|||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2Keyboard : IKeyboardDriver2, IKeyboardDriver
|
||||
class Sdl2Keyboard : IKeyboardDriver2
|
||||
{
|
||||
KeyboardState state;
|
||||
|
||||
|
@ -42,13 +42,6 @@ namespace OpenTK.Platform.SDL2
|
|||
public Sdl2Keyboard()
|
||||
{
|
||||
state.IsConnected = true;
|
||||
|
||||
keyboards.Add(new KeyboardDevice());
|
||||
keyboards[0].Description = "Standard keyboard";
|
||||
keyboards[0].NumberOfFunctionKeys = 12;
|
||||
keyboards[0].NumberOfKeys = 101;
|
||||
keyboards[0].NumberOfLeds = 3;
|
||||
keyboards_readonly = keyboards.AsReadOnly();
|
||||
}
|
||||
|
||||
#region Private Members
|
||||
|
@ -65,16 +58,16 @@ namespace OpenTK.Platform.SDL2
|
|||
{
|
||||
Keymod mod = SDL.GetModState();
|
||||
|
||||
state.SetKeyState(Key.LAlt, (byte)Scancode.LALT, (mod & Keymod.LALT) != 0);
|
||||
state.SetKeyState(Key.RAlt, (byte)Scancode.RALT, (mod & Keymod.RALT) != 0);
|
||||
state.SetKeyState(Key.LControl, (byte)Scancode.LCTRL, (mod & Keymod.LCTRL) != 0);
|
||||
state.SetKeyState(Key.RControl, (byte)Scancode.RCTRL, (mod & Keymod.CTRL) != 0);
|
||||
state.SetKeyState(Key.LShift, (byte)Scancode.LSHIFT, (mod & Keymod.LSHIFT) != 0);
|
||||
state.SetKeyState(Key.RShift, (byte)Scancode.RSHIFT, (mod & Keymod.RSHIFT) != 0);
|
||||
state.SetKeyState(Key.Menu, (byte)Scancode.APPLICATION, (mod & Keymod.GUI) != 0);
|
||||
state.SetKeyState(Key.CapsLock, (byte)Scancode.CAPSLOCK, (mod & Keymod.CAPS) != 0);
|
||||
state.SetKeyState(Key.NumLock, (byte)Scancode.NUMLOCKCLEAR, (mod & Keymod.NUM) != 0);
|
||||
//state.SetKeyState(Key., (byte)Scancode.MODE, (mod & Keymod.MODE) != 0);
|
||||
state[Key.LAlt] = (mod & Keymod.LALT) != 0;
|
||||
state[Key.RAlt] = (mod & Keymod.RALT) != 0;
|
||||
state[Key.LControl] = (mod & Keymod.LCTRL) != 0;
|
||||
state[Key.RControl] = (mod & Keymod.RCTRL) != 0;
|
||||
state[Key.LShift] = (mod & Keymod.LSHIFT) != 0;
|
||||
state[Key.RShift] = (mod & Keymod.RSHIFT) != 0;
|
||||
state[Key.Menu] = (mod & Keymod.GUI) != 0;
|
||||
state[Key.CapsLock] = (mod & Keymod.CAPS) != 0;
|
||||
state[Key.NumLock] = (mod & Keymod.NUM) != 0;
|
||||
//state[Key.] = (mod & Keymod.MODE) != 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -86,22 +79,11 @@ namespace OpenTK.Platform.SDL2
|
|||
bool pressed = e.State != 0;
|
||||
var scancode = e.Keysym.Scancode;
|
||||
Key key = Sdl2KeyMap.GetKey(scancode);
|
||||
KeyModifiers mods = Sdl2KeyMap.GetModifiers(e.Keysym.Mod);
|
||||
|
||||
if (key != Key.Unknown)
|
||||
{
|
||||
state.SetKeyState(key, (byte)scancode, pressed);
|
||||
keyboards[0].SetKey(key, (byte)scancode, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IKeyboardDriver Members
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get
|
||||
{
|
||||
return keyboards_readonly;
|
||||
state[key] = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -97,34 +87,19 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
public void ProcessWheelEvent(MouseWheelEvent wheel)
|
||||
{
|
||||
state.WheelPrecise += wheel.Y;
|
||||
mice[0].WheelPrecise += wheel.Y;
|
||||
state.SetScrollRelative(0, 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
|
||||
|
|
|
@ -41,7 +41,7 @@ using System.Text;
|
|||
|
||||
namespace OpenTK.Platform.SDL2
|
||||
{
|
||||
class Sdl2NativeWindow : INativeWindow, IInputDriver
|
||||
class Sdl2NativeWindow : NativeWindowBase
|
||||
{
|
||||
readonly object sync = new object();
|
||||
|
||||
|
@ -66,25 +66,14 @@ namespace OpenTK.Platform.SDL2
|
|||
// to .Net UTF16 strings
|
||||
char[] DecodeTextBuffer = new char[32];
|
||||
|
||||
// Argument for KeyPress event (allocated once to avoid runtime allocations)
|
||||
readonly KeyPressEventArgs keypress_args = new KeyPressEventArgs('\0');
|
||||
|
||||
// Argument for KeyDown and KeyUp events (allocated once to avoid runtime allocations)
|
||||
readonly KeyboardKeyEventArgs key_args = new KeyboardKeyEventArgs();
|
||||
|
||||
readonly IInputDriver input_driver;
|
||||
|
||||
static readonly Dictionary<uint, Sdl2NativeWindow> windows =
|
||||
new Dictionary<uint, Sdl2NativeWindow>();
|
||||
|
||||
public Sdl2NativeWindow(int x, int y, int width, int height,
|
||||
string title, GameWindowFlags options, DisplayDevice device,
|
||||
IInputDriver input_driver)
|
||||
string title, GameWindowFlags options, DisplayDevice device)
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
this.input_driver = input_driver;
|
||||
|
||||
var bounds = device.Bounds;
|
||||
var flags = TranslateFlags(options);
|
||||
flags |= WindowFlags.OPENGL;
|
||||
|
@ -180,7 +169,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;
|
||||
|
@ -188,7 +177,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;
|
||||
|
@ -196,7 +185,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;
|
||||
|
@ -214,9 +203,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.
|
||||
|
@ -225,24 +214,30 @@ namespace OpenTK.Platform.SDL2
|
|||
SDL.SetWindowGrab(window.window.Handle,
|
||||
button_pressed ? true : false);
|
||||
}
|
||||
|
||||
MouseButton button = Sdl2Mouse.TranslateButton(ev.Button);
|
||||
if (button_pressed)
|
||||
{
|
||||
window.OnMouseDown(button);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.OnMouseUp(button);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessKeyEvent(Sdl2NativeWindow window, Event ev)
|
||||
{
|
||||
bool key_pressed = ev.Key.State == State.Pressed;
|
||||
var key = ev.Key.Keysym;
|
||||
window.key_args.Key = TranslateKey(key.Scancode);
|
||||
window.key_args.ScanCode = (uint)key.Scancode;
|
||||
window.key_args.Modifiers = window.input_driver.Keyboard[0].GetModifiers();
|
||||
Key key = TranslateKey(ev.Key.Keysym.Scancode);
|
||||
if (key_pressed)
|
||||
{
|
||||
window.KeyDown(window, window.key_args);
|
||||
window.OnKeyDown(key, ev.Key.Repeat > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.KeyUp(window, window.key_args);
|
||||
window.OnKeyUp(key);
|
||||
}
|
||||
//window.keyboard.SetKey(TranslateKey(key.scancode), (uint)key.scancode, key_pressed);
|
||||
}
|
||||
|
||||
static unsafe void ProcessTextInputEvent(Sdl2NativeWindow window, TextInputEvent ev)
|
||||
|
@ -273,21 +268,21 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
for (int i = 0; i < decoded_length; i++)
|
||||
{
|
||||
window.keypress_args.KeyChar = window.DecodeTextBuffer[i];
|
||||
window.KeyPress(window, window.keypress_args);
|
||||
window.OnKeyPress(window.DecodeTextBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessMotionEvent(Sdl2NativeWindow window, Event ev)
|
||||
static void ProcessMouseMotionEvent(Sdl2NativeWindow window, MouseMotionEvent ev)
|
||||
{
|
||||
float scale = window.ClientSize.Width / (float)window.Size.Width;
|
||||
//window.mouse.Position = new Point(
|
||||
// (int)(ev.motion.x * scale), (int)(ev.motion.y * scale));
|
||||
window.OnMouseMove(
|
||||
(int)Math.Round(ev.X * scale),
|
||||
(int)Math.Round(ev.Y * scale));
|
||||
}
|
||||
|
||||
static void ProcessWheelEvent(Sdl2NativeWindow window, Event ev)
|
||||
static void ProcessMouseWheelEvent(Sdl2NativeWindow window, MouseWheelEvent ev)
|
||||
{
|
||||
//window.mouse.Wheel += ev.wheel.y;
|
||||
window.OnMouseWheel(ev.X, ev.Y);
|
||||
}
|
||||
|
||||
static void ProcessWindowEvent(Sdl2NativeWindow window, WindowEvent e)
|
||||
|
@ -299,7 +294,7 @@ namespace OpenTK.Platform.SDL2
|
|||
try
|
||||
{
|
||||
window.is_in_closing_event = true;
|
||||
window.Closing(window, close_args);
|
||||
window.OnClosing(close_args);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -308,17 +303,17 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
if (!close_args.Cancel)
|
||||
{
|
||||
window.Closed(window, EventArgs.Empty);
|
||||
window.OnClosed(EventArgs.Empty);
|
||||
window.must_destroy = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case WindowEventID.ENTER:
|
||||
window.MouseEnter(window, EventArgs.Empty);
|
||||
window.OnMouseEnter(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.LEAVE:
|
||||
window.MouseLeave(window, EventArgs.Empty);
|
||||
window.OnMouseLeave(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.EXPOSED:
|
||||
|
@ -327,47 +322,47 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
case WindowEventID.FOCUS_GAINED:
|
||||
window.is_focused = true;
|
||||
window.FocusedChanged(window, EventArgs.Empty);
|
||||
window.OnFocusedChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.FOCUS_LOST:
|
||||
window.is_focused = false;
|
||||
window.FocusedChanged(window, EventArgs.Empty);
|
||||
window.OnFocusedChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.HIDDEN:
|
||||
window.is_visible = false;
|
||||
window.VisibleChanged(window, EventArgs.Empty);
|
||||
window.OnVisibleChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.SHOWN:
|
||||
window.is_visible = true;
|
||||
window.VisibleChanged(window, EventArgs.Empty);
|
||||
window.OnVisibleChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.MAXIMIZED:
|
||||
window.window_state = WindowState.Maximized;
|
||||
window.WindowStateChanged(window, EventArgs.Empty);
|
||||
window.OnWindowStateChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.MINIMIZED:
|
||||
window.previous_window_state = window.window_state;
|
||||
window.window_state = WindowState.Minimized;
|
||||
window.WindowStateChanged(window, EventArgs.Empty);
|
||||
window.OnWindowStateChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.RESTORED:
|
||||
window.window_state = window.previous_window_state;
|
||||
window.WindowStateChanged(window, EventArgs.Empty);
|
||||
window.OnWindowStateChanged(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.MOVED:
|
||||
window.Move(window, EventArgs.Empty);
|
||||
window.OnMove(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case WindowEventID.RESIZED:
|
||||
case WindowEventID.SIZE_CHANGED:
|
||||
window.Resize(window, EventArgs.Empty);
|
||||
window.OnResize(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -402,6 +397,16 @@ namespace OpenTK.Platform.SDL2
|
|||
SDL.ShowCursor(!grab);
|
||||
SDL.SetWindowGrab(window.Handle, grab);
|
||||
SDL.SetRelativeMouseMode(grab);
|
||||
if (!grab)
|
||||
{
|
||||
// Move the cursor to the current position
|
||||
// in order to avoid a sudden jump when it
|
||||
// becomes visible again
|
||||
float scale = Width / (float)Size.Width;
|
||||
SDL.WarpMouseInWindow(window.Handle,
|
||||
(int)Math.Round(MouseState.X / scale),
|
||||
(int)Math.Round(MouseState.Y / scale));
|
||||
}
|
||||
}
|
||||
|
||||
// Hack to force WindowState events to be pumped
|
||||
|
@ -443,24 +448,7 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
#region INativeWindow Members
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
|
||||
public MouseCursor Cursor
|
||||
public override MouseCursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -540,7 +528,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
public override void Close()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
|
@ -560,8 +548,9 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public void ProcessEvents()
|
||||
public override void ProcessEvents()
|
||||
{
|
||||
base.ProcessEvents();
|
||||
lock (sync)
|
||||
{
|
||||
if (Exists)
|
||||
|
@ -581,21 +570,21 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public Point PointToClient(Point point)
|
||||
public override Point PointToClient(Point point)
|
||||
{
|
||||
var origin = DisplayDevice.Default.Bounds.Location;
|
||||
var client = Location;
|
||||
return new Point(point.X + client.X - origin.X, point.Y + client.Y - origin.Y);
|
||||
}
|
||||
|
||||
public Point PointToScreen(Point point)
|
||||
public override Point PointToScreen(Point point)
|
||||
{
|
||||
var origin = DisplayDevice.Default.Bounds.Location;
|
||||
var client = Location;
|
||||
return new Point(point.X + origin.X - client.X, point.Y + origin.Y - client.Y);
|
||||
}
|
||||
|
||||
public Icon Icon
|
||||
public override Icon Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -639,13 +628,13 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
|
||||
icon = value;
|
||||
IconChanged(this, EventArgs.Empty);
|
||||
OnIconChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
public override string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -671,7 +660,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public bool Focused
|
||||
public override bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -679,7 +668,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -700,7 +689,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public bool Exists
|
||||
public override bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -708,7 +697,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public IWindowInfo WindowInfo
|
||||
public override IWindowInfo WindowInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -716,7 +705,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public WindowState WindowState
|
||||
public override WindowState WindowState
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -774,7 +763,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public WindowBorder WindowBorder
|
||||
public override WindowBorder WindowBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -810,13 +799,13 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
if (Exists)
|
||||
{
|
||||
WindowBorderChanged(this, EventArgs.Empty);
|
||||
OnWindowBorderChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Bounds
|
||||
public override Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -829,7 +818,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public Point Location
|
||||
public override Point Location
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -856,7 +845,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public Size Size
|
||||
public override Size Size
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -883,67 +872,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get
|
||||
{
|
||||
return Location.X;
|
||||
}
|
||||
set
|
||||
{
|
||||
Location = new Point(value, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return Location.Y;
|
||||
}
|
||||
set
|
||||
{
|
||||
Location = new Point(X, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientSize.Width;
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientSize = new Size(value, Height);
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientSize.Height;
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientSize = new Size(Width, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle ClientRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Rectangle(new Point(), ClientSize);
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientSize = value.Size;
|
||||
}
|
||||
}
|
||||
|
||||
public Size ClientSize
|
||||
public override Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -967,15 +896,7 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public IInputDriver InputDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
return input_driver;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CursorVisible
|
||||
public override bool CursorVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -996,54 +917,9 @@ namespace OpenTK.Platform.SDL2
|
|||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver Members
|
||||
|
||||
public void Poll()
|
||||
{
|
||||
InputDriver.Poll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IJoystickDriver Members
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get
|
||||
{
|
||||
return InputDriver.Joysticks;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouseDriver Members
|
||||
|
||||
public IList<MouseDevice> Mouse
|
||||
{
|
||||
get
|
||||
{
|
||||
return InputDriver.Mouse;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IKeyboardDriver Members
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get
|
||||
{
|
||||
return InputDriver.Keyboard;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
void Dispose(bool manual)
|
||||
protected override void Dispose(bool manual)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
|
@ -1082,17 +958,6 @@ namespace OpenTK.Platform.SDL2
|
|||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Sdl2NativeWindow()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3591,7 +3591,8 @@ namespace OpenTK.Platform.Windows
|
|||
BUTTON_5_DOWN = 0x0100,
|
||||
BUTTON_5_UP = 0x0200,
|
||||
|
||||
WHEEL = 0x0400
|
||||
WHEEL = 0x0400,
|
||||
HWHEEL = 0x0800,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -4197,7 +4198,6 @@ namespace OpenTK.Platform.Windows
|
|||
MBUTTONUP = 0x0208,
|
||||
MBUTTONDBLCLK = 0x0209,
|
||||
MOUSEWHEEL = 0x020A,
|
||||
MOUSELAST = 0x020D,
|
||||
/// <summary>
|
||||
/// Windows 2000 and higher only.
|
||||
/// </summary>
|
||||
|
@ -4210,6 +4210,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,
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace OpenTK.Platform.Windows
|
|||
/// Drives GameWindow on Windows.
|
||||
/// This class supports OpenTK, and is not intended for use by OpenTK programs.
|
||||
/// </summary>
|
||||
internal sealed class WinGLNative : INativeWindow, IInputDriver
|
||||
internal sealed class WinGLNative : NativeWindowBase
|
||||
{
|
||||
#region Fields
|
||||
|
||||
|
@ -82,12 +82,6 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
const ClassStyle DefaultClassStyle = ClassStyle.OwnDC;
|
||||
|
||||
// Used for IInputDriver implementation
|
||||
IJoystickDriver joystick_driver = Factory.Default.CreateLegacyJoystickDriver();
|
||||
KeyboardDevice keyboard = new KeyboardDevice();
|
||||
MouseDevice mouse = new MouseDevice();
|
||||
IList<KeyboardDevice> keyboards = new List<KeyboardDevice>(1);
|
||||
IList<MouseDevice> mice = new List<MouseDevice>(1);
|
||||
const long ExtendedBit = 1 << 24; // Used to distinguish left and right control, alt and enter keys.
|
||||
|
||||
public static readonly uint ShiftLeftScanCode = Functions.MapVirtualKey(VirtualKeys.LSHIFT, 0);
|
||||
|
@ -97,10 +91,6 @@ namespace OpenTK.Platform.Windows
|
|||
public static readonly uint AltLeftScanCode = Functions.MapVirtualKey(VirtualKeys.LMENU, 0);
|
||||
public static readonly uint AltRightScanCode = Functions.MapVirtualKey(VirtualKeys.RMENU, 0);
|
||||
|
||||
KeyboardKeyEventArgs key_down = new KeyboardKeyEventArgs();
|
||||
KeyboardKeyEventArgs key_up = new KeyboardKeyEventArgs();
|
||||
KeyPressEventArgs key_press = new KeyPressEventArgs((char)0);
|
||||
|
||||
MouseCursor cursor = MouseCursor.Default;
|
||||
IntPtr cursor_handle = Functions.LoadCursor(CursorName.Arrow);
|
||||
int cursor_visible_count = 0;
|
||||
|
@ -160,18 +150,6 @@ namespace OpenTK.Platform.Windows
|
|||
window);
|
||||
|
||||
exists = true;
|
||||
|
||||
keyboard.Description = "Standard Windows keyboard";
|
||||
keyboard.NumberOfFunctionKeys = 12;
|
||||
keyboard.NumberOfKeys = 101;
|
||||
keyboard.NumberOfLeds = 3;
|
||||
|
||||
mouse.Description = "Standard Windows mouse";
|
||||
mouse.NumberOfButtons = 3;
|
||||
mouse.NumberOfWheels = 1;
|
||||
|
||||
keyboards.Add(keyboard);
|
||||
mice.Add(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +232,7 @@ namespace OpenTK.Platform.Windows
|
|||
focused = (wParam.ToInt64() & 0xFFFF) != 0;
|
||||
|
||||
if (new_focused_state != Focused)
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
OnFocusedChanged(EventArgs.Empty);
|
||||
}
|
||||
|
||||
void HandleEnterModalLoop(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -292,7 +270,7 @@ namespace OpenTK.Platform.Windows
|
|||
if (Location != new_location)
|
||||
{
|
||||
bounds.Location = new_location;
|
||||
Move(this, EventArgs.Empty);
|
||||
OnMove(EventArgs.Empty);
|
||||
}
|
||||
|
||||
Size new_size = new Size(pos->cx, pos->cy);
|
||||
|
@ -310,7 +288,7 @@ namespace OpenTK.Platform.Windows
|
|||
SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING);
|
||||
|
||||
if (suppress_resize <= 0)
|
||||
Resize(this, EventArgs.Empty);
|
||||
OnResize(EventArgs.Empty);
|
||||
}
|
||||
|
||||
if (!is_in_modal_loop)
|
||||
|
@ -352,7 +330,7 @@ namespace OpenTK.Platform.Windows
|
|||
GrabCursor();
|
||||
|
||||
windowBorder = new_border;
|
||||
WindowBorderChanged(this, EventArgs.Empty);
|
||||
OnWindowBorderChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,7 +358,7 @@ namespace OpenTK.Platform.Windows
|
|||
if (new_state != windowState)
|
||||
{
|
||||
windowState = new_state;
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
|
||||
// Ensure cursor remains grabbed
|
||||
if (!CursorVisible)
|
||||
|
@ -415,8 +393,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
if (!Char.IsControl(c))
|
||||
{
|
||||
key_press.KeyChar = c;
|
||||
KeyPress(this, key_press);
|
||||
OnKeyPress(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,8 +419,7 @@ namespace OpenTK.Platform.Windows
|
|||
};
|
||||
|
||||
// Max points GetMouseMovePointsEx can return is 64.
|
||||
int numPoints = 64;
|
||||
|
||||
const int numPoints = 64;
|
||||
MouseMovePoint* movePoints = stackalloc MouseMovePoint[numPoints];
|
||||
|
||||
// GetMouseMovePointsEx fills in movePoints so that the most
|
||||
|
@ -459,7 +435,7 @@ namespace OpenTK.Platform.Windows
|
|||
if (points == 0 || (points == -1 && lastError == Constants.ERROR_POINT_NOT_FOUND))
|
||||
{
|
||||
// Just use the mouse move position
|
||||
mouse.Position = point;
|
||||
OnMouseMove(point.X, point.Y);
|
||||
}
|
||||
else if (points == -1)
|
||||
{
|
||||
|
@ -468,7 +444,7 @@ namespace OpenTK.Platform.Windows
|
|||
else
|
||||
{
|
||||
// Exclude the current position.
|
||||
Point currentScreenPosition = new Point(mouse.X, mouse.Y);
|
||||
Point currentScreenPosition = new Point(InputDriver.Mouse[0].X, InputDriver.Mouse[0].Y);
|
||||
Functions.ClientToScreen(handle, ref currentScreenPosition);
|
||||
|
||||
// Find the first move point we've already seen.
|
||||
|
@ -497,7 +473,7 @@ namespace OpenTK.Platform.Windows
|
|||
position.Y -= 65536;
|
||||
}
|
||||
Functions.ScreenToClient(handle, ref position);
|
||||
mouse.Position = position;
|
||||
OnMouseMove(position.X, position.Y);
|
||||
}
|
||||
}
|
||||
mouse_last_timestamp = timestamp;
|
||||
|
@ -510,7 +486,7 @@ namespace OpenTK.Platform.Windows
|
|||
mouse_outside_window = false;
|
||||
EnableMouseTracking();
|
||||
|
||||
MouseEnter(this, EventArgs.Empty);
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,64 +495,75 @@ namespace OpenTK.Platform.Windows
|
|||
mouse_outside_window = true;
|
||||
// Mouse tracking is disabled automatically by the OS
|
||||
|
||||
MouseLeave(this, EventArgs.Empty);
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
}
|
||||
|
||||
void HandleMouseWheel(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
|
||||
mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f;
|
||||
OnMouseWheel(0, ((long)wParam << 32 >> 48) / 120.0f);
|
||||
}
|
||||
|
||||
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
|
||||
OnMouseWheel(((long)wParam << 32 >> 48) / 120.0f, 0);
|
||||
}
|
||||
|
||||
void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
mouse[MouseButton.Left] = true;
|
||||
OnMouseDown(MouseButton.Left);
|
||||
}
|
||||
|
||||
void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
mouse[MouseButton.Middle] = true;
|
||||
OnMouseDown(MouseButton.Middle);
|
||||
}
|
||||
|
||||
void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
mouse[MouseButton.Right] = true;
|
||||
OnMouseDown(MouseButton.Right);
|
||||
}
|
||||
|
||||
void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.SetCapture(window.Handle);
|
||||
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2] = true;
|
||||
MouseButton button =
|
||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2;
|
||||
OnMouseDown(button);
|
||||
}
|
||||
|
||||
void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
mouse[MouseButton.Left] = false;
|
||||
OnMouseUp(MouseButton.Left);
|
||||
}
|
||||
|
||||
void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
mouse[MouseButton.Middle] = false;
|
||||
OnMouseUp(MouseButton.Middle);
|
||||
}
|
||||
|
||||
void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
mouse[MouseButton.Right] = false;
|
||||
OnMouseUp(MouseButton.Right);
|
||||
}
|
||||
|
||||
void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Functions.ReleaseCapture();
|
||||
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2] = false;
|
||||
MouseButton button =
|
||||
((wParam.ToInt32() & 0xFFFF0000) >> 16) == 1 ?
|
||||
MouseButton.Button1 : MouseButton.Button2;
|
||||
OnMouseUp(button);
|
||||
}
|
||||
|
||||
void HandleKeyboard(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -593,33 +580,28 @@ namespace OpenTK.Platform.Windows
|
|||
// In this case, both keys will be reported as pressed.
|
||||
|
||||
bool extended = (lParam.ToInt64() & ExtendedBit) != 0;
|
||||
short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF);
|
||||
short scancode = (short)((lParam.ToInt64() >> 16) & 0xff);
|
||||
//ushort repeat_count = unchecked((ushort)((ulong)lParam.ToInt64() & 0xffffu));
|
||||
VirtualKeys vkey = (VirtualKeys)wParam;
|
||||
bool is_valid;
|
||||
Key key = WinKeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid);
|
||||
|
||||
if (is_valid)
|
||||
{
|
||||
keyboard.SetKey(key, (byte)scancode, pressed);
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
key_down.Key = key;
|
||||
key_down.Modifiers = keyboard.GetModifiers();
|
||||
KeyDown(this, key_down);
|
||||
//OnKeyDown(key, repeat_count > 0);
|
||||
OnKeyDown(key, KeyboardState[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
key_up.Key = key;
|
||||
key_up.Modifiers = keyboard.GetModifiers();
|
||||
KeyUp(this, key_up);
|
||||
OnKeyUp(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleKillFocus(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
keyboard.ClearKeys();
|
||||
}
|
||||
|
||||
void HandleCreate(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
|
||||
|
@ -644,7 +626,7 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs();
|
||||
|
||||
Closing(this, e);
|
||||
OnClosing(e);
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
|
@ -663,7 +645,7 @@ namespace OpenTK.Platform.Windows
|
|||
window.Dispose();
|
||||
child_window.Dispose();
|
||||
|
||||
Closed(this, EventArgs.Empty);
|
||||
OnClosed(EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -731,6 +713,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;
|
||||
|
@ -927,7 +913,6 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
suppress_resize++;
|
||||
WindowBorder = WindowBorder.Hidden;
|
||||
ProcessEvents();
|
||||
suppress_resize--;
|
||||
}
|
||||
|
||||
|
@ -938,7 +923,6 @@ namespace OpenTK.Platform.Windows
|
|||
deferred_window_border.HasValue ? deferred_window_border.Value :
|
||||
previous_window_border.HasValue ? previous_window_border.Value :
|
||||
WindowBorder;
|
||||
ProcessEvents();
|
||||
suppress_resize--;
|
||||
deferred_window_border = previous_window_border = null;
|
||||
}
|
||||
|
@ -947,7 +931,6 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
suppress_resize++;
|
||||
WindowState = WindowState.Normal;
|
||||
ProcessEvents();
|
||||
suppress_resize--;
|
||||
}
|
||||
|
||||
|
@ -977,7 +960,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Bounds
|
||||
|
||||
public Rectangle Bounds
|
||||
public override Rectangle Bounds
|
||||
{
|
||||
get { return bounds; }
|
||||
set
|
||||
|
@ -991,7 +974,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Location
|
||||
|
||||
public Point Location
|
||||
public override Point Location
|
||||
{
|
||||
get { return Bounds.Location; }
|
||||
set
|
||||
|
@ -1005,7 +988,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Size
|
||||
|
||||
public Size Size
|
||||
public override Size Size
|
||||
{
|
||||
get { return Bounds.Size; }
|
||||
set
|
||||
|
@ -1017,36 +1000,13 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region ClientRectangle
|
||||
|
||||
public Rectangle ClientRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (client_rectangle.Width == 0)
|
||||
client_rectangle.Width = 1;
|
||||
if (client_rectangle.Height == 0)
|
||||
client_rectangle.Height = 1;
|
||||
return client_rectangle;
|
||||
}
|
||||
set
|
||||
{
|
||||
WindowStyle style = (WindowStyle)Functions.GetWindowLong(window.Handle, GetWindowLongOffsets.STYLE);
|
||||
Win32Rectangle rect = Win32Rectangle.From(value);
|
||||
Functions.AdjustWindowRect(ref rect, style, false);
|
||||
Size = new Size(rect.Width, rect.Height);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ClientSize
|
||||
|
||||
public Size ClientSize
|
||||
public override Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientRectangle.Size;
|
||||
return client_rectangle.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -1059,49 +1019,9 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region Width
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return ClientRectangle.Width; }
|
||||
set { ClientRectangle = new Rectangle(0, 0, value, Height); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Height
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return ClientRectangle.Height; }
|
||||
set { ClientRectangle = new Rectangle(0, 0, Width, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region X
|
||||
|
||||
public int X
|
||||
{
|
||||
get { return Location.X; }
|
||||
set { Location = new Point(value, Y); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Y
|
||||
|
||||
public int Y
|
||||
{
|
||||
get { return Location.Y; }
|
||||
set { Location = new Point(X, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Icon
|
||||
|
||||
public Icon Icon
|
||||
public override Icon Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1117,7 +1037,7 @@ namespace OpenTK.Platform.Windows
|
|||
Functions.SendMessage(window.Handle, WindowMessage.SETICON, (IntPtr)0, icon == null ? IntPtr.Zero : value.Handle);
|
||||
Functions.SendMessage(window.Handle, WindowMessage.SETICON, (IntPtr)1, icon == null ? IntPtr.Zero : value.Handle);
|
||||
}
|
||||
IconChanged(this, EventArgs.Empty);
|
||||
OnIconChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1126,7 +1046,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Focused
|
||||
|
||||
public bool Focused
|
||||
public override bool Focused
|
||||
{
|
||||
get { return focused; }
|
||||
}
|
||||
|
@ -1136,7 +1056,7 @@ namespace OpenTK.Platform.Windows
|
|||
#region Title
|
||||
|
||||
StringBuilder sb_title = new StringBuilder(256);
|
||||
public string Title
|
||||
public override string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1151,7 +1071,7 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
if (!Functions.SetWindowText(window.Handle, value))
|
||||
Debug.Print("Failed to change window title (window:{0}, new title:{1}, reason:{2}).", window.Handle, value, Marshal.GetLastWin32Error());
|
||||
TitleChanged(this, EventArgs.Empty);
|
||||
OnTitleChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1160,7 +1080,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Visible
|
||||
|
||||
public bool Visible
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1184,7 +1104,7 @@ namespace OpenTK.Platform.Windows
|
|||
Functions.ShowWindow(window.Handle, ShowWindowCommand.HIDE);
|
||||
}
|
||||
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
OnVisibleChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1193,13 +1113,13 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Exists
|
||||
|
||||
public bool Exists { get { return exists; } }
|
||||
public override bool Exists { get { return exists; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cursor
|
||||
|
||||
public MouseCursor Cursor
|
||||
public override MouseCursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1270,8 +1190,8 @@ namespace OpenTK.Platform.Windows
|
|||
#endregion
|
||||
|
||||
#region CursorVisible
|
||||
|
||||
public bool CursorVisible
|
||||
|
||||
public override bool CursorVisible
|
||||
{
|
||||
get { return cursor_visible_count >= 0; } // Not used
|
||||
set
|
||||
|
@ -1303,7 +1223,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region Close
|
||||
|
||||
public void Close()
|
||||
public override void Close()
|
||||
{
|
||||
Functions.PostMessage(window.Handle, WindowMessage.CLOSE, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
@ -1312,7 +1232,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region public WindowState WindowState
|
||||
|
||||
public WindowState WindowState
|
||||
public override WindowState WindowState
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1325,12 +1245,12 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
ShowWindowCommand command = 0;
|
||||
bool exiting_fullscreen = false;
|
||||
borderless_maximized_window_state = false;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case WindowState.Normal:
|
||||
command = ShowWindowCommand.RESTORE;
|
||||
borderless_maximized_window_state = false;
|
||||
|
||||
// If we are leaving fullscreen mode we need to restore the border.
|
||||
if (WindowState == WindowState.Fullscreen)
|
||||
|
@ -1358,6 +1278,7 @@ namespace OpenTK.Platform.Windows
|
|||
}
|
||||
else
|
||||
{
|
||||
borderless_maximized_window_state = false;
|
||||
command = ShowWindowCommand.MAXIMIZE;
|
||||
}
|
||||
break;
|
||||
|
@ -1406,7 +1327,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region public WindowBorder WindowBorder
|
||||
|
||||
public WindowBorder WindowBorder
|
||||
public override WindowBorder WindowBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1500,7 +1421,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region PointToClient
|
||||
|
||||
public Point PointToClient(Point point)
|
||||
public override Point PointToClient(Point point)
|
||||
{
|
||||
if (!Functions.ScreenToClient(window.Handle, ref point))
|
||||
throw new InvalidOperationException(String.Format(
|
||||
|
@ -1514,7 +1435,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#region PointToScreen
|
||||
|
||||
public Point PointToScreen(Point point)
|
||||
public override Point PointToScreen(Point point)
|
||||
{
|
||||
if (!Functions.ClientToScreen(window.Handle, ref point))
|
||||
throw new InvalidOperationException(String.Format(
|
||||
|
@ -1526,27 +1447,6 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region INativeGLWindow Members
|
||||
|
@ -1554,8 +1454,9 @@ namespace OpenTK.Platform.Windows
|
|||
#region public void ProcessEvents()
|
||||
|
||||
MSG msg;
|
||||
public void ProcessEvents()
|
||||
public override void ProcessEvents()
|
||||
{
|
||||
base.ProcessEvents();
|
||||
while (Functions.PeekMessage(ref msg, IntPtr.Zero, 0, 0, PeekMessageFlags.Remove))
|
||||
{
|
||||
Functions.TranslateMessage(ref msg);
|
||||
|
@ -1565,18 +1466,9 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region public IInputDriver InputDriver
|
||||
|
||||
public IInputDriver InputDriver
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public IWindowInfo WindowInfo
|
||||
|
||||
public IWindowInfo WindowInfo
|
||||
public override IWindowInfo WindowInfo
|
||||
{
|
||||
get { return child_window; }
|
||||
}
|
||||
|
@ -1585,62 +1477,9 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region IInputDriver Members
|
||||
|
||||
public void Poll()
|
||||
{
|
||||
if (joystick_driver is WinMMJoystick)
|
||||
(joystick_driver as WinMMJoystick).Poll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IKeyboardDriver Members
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get { return keyboards; }
|
||||
}
|
||||
|
||||
public KeyboardState GetState()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public KeyboardState GetState(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouseDriver Members
|
||||
|
||||
public IList<MouseDevice> Mouse
|
||||
{
|
||||
get { return mice; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IJoystickDriver Members
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get { return joystick_driver.Joysticks; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void Dispose(bool calledManually)
|
||||
protected override void Dispose(bool calledManually)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
|
@ -1662,16 +1501,11 @@ namespace OpenTK.Platform.Windows
|
|||
Debug.Print("[Warning] INativeWindow leaked ({0}). Did you forget to call INativeWindow.Dispose()?", this);
|
||||
}
|
||||
|
||||
Disposed(this, EventArgs.Empty);
|
||||
OnDisposed(EventArgs.Empty);
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~WinGLNative()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
if (is_valid)
|
||||
{
|
||||
keyboard.SetKeyState(key, (byte)scancode, pressed);
|
||||
keyboard.SetKeyState(key, pressed);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,10 @@ namespace OpenTK.Platform.Windows
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -266,7 +266,14 @@ namespace OpenTK.Platform.X11
|
|||
static string[] EntryPointNames = new string[]
|
||||
{
|
||||
"glXCreateContextAttribs",
|
||||
"glXSwapIntervalEXT",
|
||||
"glXGetSwapIntervalEXT",
|
||||
"glXSwapIntervalMESA",
|
||||
"glXGetSwapIntervalMESA",
|
||||
"glXSwapIntervalOML",
|
||||
"glXGetSwapIntervalOML",
|
||||
"glXSwapIntervalSGI",
|
||||
"glXGetSwapIntervalSGI",
|
||||
};
|
||||
static IntPtr[] EntryPoints = new IntPtr[EntryPointNames.Length];
|
||||
|
||||
|
@ -405,6 +412,36 @@ namespace OpenTK.Platform.X11
|
|||
#endregion
|
||||
}
|
||||
|
||||
public partial class Ext
|
||||
{
|
||||
[AutoGenerated(EntryPoint = "glXSwapIntervalEXT")]
|
||||
public static ErrorCode SwapInterval(int interval)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[AutoGenerated(EntryPoint = "glXGetSwapIntervalEXT")]
|
||||
public static int GetSwapInterval()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Mesa
|
||||
{
|
||||
[AutoGenerated(EntryPoint = "glXSwapIntervalMESA")]
|
||||
public static ErrorCode SwapInterval(int interval)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[AutoGenerated(EntryPoint = "glXGetSwapIntervalMESA")]
|
||||
public static int GetSwapInterval()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Sgi
|
||||
{
|
||||
[AutoGenerated(EntryPoint = "glXSwapIntervalSGI")]
|
||||
|
@ -412,6 +449,12 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[AutoGenerated(EntryPoint = "glXGetSwapIntervalSGI")]
|
||||
public static int GetSwapInterval()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[Slot(0)]
|
||||
|
@ -419,7 +462,22 @@ namespace OpenTK.Platform.X11
|
|||
internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
|
||||
[Slot(1)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern IntPtr glXSwapIntervalSGI(int interval);
|
||||
internal static extern ErrorCode glXSwapIntervalEXT(int interval);
|
||||
[Slot(2)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int glXGetSwapIntervalEXT();
|
||||
[Slot(3)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern ErrorCode glXSwapIntervalMESA(int interval);
|
||||
[Slot(4)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int glXGetSwapIntervalMESA();
|
||||
[Slot(5)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern ErrorCode glXSwapIntervalSGI(int interval);
|
||||
[Slot(6)]
|
||||
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern int glXGetSwapIntervalSGI();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1707,7 +1707,7 @@ namespace OpenTK.Platform.X11
|
|||
public double root_y;
|
||||
public double event_x;
|
||||
public double event_y;
|
||||
public int flags;
|
||||
public XIEventFlags flags;
|
||||
public XIButtonState buttons;
|
||||
public XIValuatorState valuators;
|
||||
public XIModifierState mods;
|
||||
|
@ -1828,4 +1828,32 @@ namespace OpenTK.Platform.X11
|
|||
RawButtonReleaseMask = (1 << (int)XIEventType.RawButtonRelease),
|
||||
RawMotionMask = (1 << (int)XIEventType.RawMotion),
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum XIKeyEventFlags
|
||||
{
|
||||
Repeat = (1 << 16),
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum XIPointerEventFlags
|
||||
{
|
||||
Emulated = (1 << 16),
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum XITouchEventFlags
|
||||
{
|
||||
PendingEnd = (1 << 16),
|
||||
EmulatingPointer = (1 << 17),
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum XIEventFlags
|
||||
{
|
||||
KeyRepeat = XIKeyEventFlags.Repeat,
|
||||
PointerEmulated = XIPointerEventFlags.Emulated,
|
||||
TouchPendingEnd = XITouchEventFlags.PendingEnd,
|
||||
TouchEmulatingPointer = XITouchEventFlags.EmulatingPointer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,13 @@ namespace OpenTK.Platform.X11
|
|||
// current on window originating from a different display.
|
||||
IntPtr display;
|
||||
X11WindowInfo currentWindow;
|
||||
bool vsync_supported;
|
||||
bool vsync_ext_supported;
|
||||
bool vsync_mesa_supported;
|
||||
bool vsync_sgi_supported;
|
||||
bool vsync_tear_supported;
|
||||
int swap_interval = 1; // As defined in GLX_SGI_swap_control
|
||||
int sgi_swap_interval = 1; // As defined in GLX_SGI_swap_control
|
||||
readonly X11GraphicsMode ModeSelector = new X11GraphicsMode();
|
||||
string extensions = null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -232,7 +235,7 @@ namespace OpenTK.Platform.X11
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool SupportsExtension(IntPtr display, X11WindowInfo window, string e)
|
||||
bool SupportsExtension(IntPtr display, X11WindowInfo window, string e)
|
||||
{
|
||||
if (window == null)
|
||||
throw new ArgumentNullException("window");
|
||||
|
@ -241,15 +244,17 @@ namespace OpenTK.Platform.X11
|
|||
if (window.Display != display)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
string extensions = null;
|
||||
using (new XLock(display))
|
||||
if (String.IsNullOrEmpty(extensions))
|
||||
{
|
||||
extensions = Glx.QueryExtensionsString(display, window.Screen);
|
||||
using (new XLock(display))
|
||||
{
|
||||
extensions = Glx.QueryExtensionsString(display, window.Screen);
|
||||
}
|
||||
}
|
||||
return !String.IsNullOrEmpty(extensions) && extensions.Contains(e);
|
||||
}
|
||||
|
||||
static bool SupportsCreateContextAttribs(IntPtr display, X11WindowInfo window)
|
||||
bool SupportsCreateContextAttribs(IntPtr display, X11WindowInfo window)
|
||||
{
|
||||
return
|
||||
SupportsExtension(display, window, "GLX_ARB_create_context") &&
|
||||
|
@ -354,29 +359,40 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
get
|
||||
{
|
||||
if (vsync_supported)
|
||||
return swap_interval;
|
||||
else
|
||||
return 0;
|
||||
using (new XLock(display))
|
||||
{
|
||||
if (vsync_ext_supported)
|
||||
return Glx.Ext.GetSwapInterval();
|
||||
else if (vsync_mesa_supported)
|
||||
return Glx.Mesa.GetSwapInterval();
|
||||
else if (vsync_sgi_supported)
|
||||
return sgi_swap_interval;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (vsync_supported)
|
||||
if (value < 0 && !vsync_tear_supported)
|
||||
{
|
||||
if (value < 0 && !vsync_tear_supported)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
|
||||
ErrorCode error_code = 0;
|
||||
using (new XLock(Display))
|
||||
error_code = Glx.Sgi.SwapInterval(value);
|
||||
|
||||
if (error_code == X11.ErrorCode.NO_ERROR)
|
||||
swap_interval = value;
|
||||
else
|
||||
Debug.Print("VSync = {0} failed, error code: {1}.", value, error_code);
|
||||
value = 1;
|
||||
}
|
||||
|
||||
ErrorCode error_code = 0;
|
||||
using (new XLock(Display))
|
||||
{
|
||||
if (vsync_ext_supported)
|
||||
error_code = Glx.Ext.SwapInterval(value);
|
||||
else if (vsync_mesa_supported)
|
||||
error_code = Glx.Mesa.SwapInterval(value);
|
||||
else if (vsync_sgi_supported)
|
||||
error_code = Glx.Sgi.SwapInterval(value);
|
||||
}
|
||||
|
||||
if (error_code == X11.ErrorCode.NO_ERROR)
|
||||
sgi_swap_interval = value;
|
||||
else
|
||||
Debug.Print("VSync = {0} failed, error code: {1}.", value, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,12 +402,23 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
public override void LoadAll()
|
||||
{
|
||||
vsync_supported =
|
||||
vsync_ext_supported =
|
||||
SupportsExtension(display, currentWindow, "GLX_EXT_swap_control") &&
|
||||
Glx.SupportsFunction("glXSwapIntervalEXT") &&
|
||||
Glx.SupportsFunction("glXGetSwapIntervalEXT");
|
||||
vsync_mesa_supported =
|
||||
SupportsExtension(display, currentWindow, "GLX_MESA_swap_control") &&
|
||||
Glx.SupportsFunction("glXSwapIntervalMESA") &&
|
||||
Glx.SupportsFunction("glXGetSwapIntervalMESA");
|
||||
vsync_sgi_supported =
|
||||
SupportsExtension(display, currentWindow, "GLX_SGI_swap_control") &&
|
||||
Glx.SupportsFunction("glXSwapIntervalSGI");
|
||||
Debug.Print("Context supports vsync: {0}.",
|
||||
vsync_ext_supported || vsync_mesa_supported || vsync_ext_supported);
|
||||
|
||||
vsync_tear_supported =
|
||||
SupportsExtension(display, currentWindow, "GLX_EXT_swap_control_tear");
|
||||
Debug.Print("Context supports vsync: {0}.", vsync_supported);
|
||||
Debug.Print("Context supports vsync tear: {0}.", vsync_tear_supported);
|
||||
|
||||
base.LoadAll();
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace OpenTK.Platform.X11
|
|||
/// Drives GameWindow on X11.
|
||||
/// This class supports OpenTK, and is not intended for use by OpenTK programs.
|
||||
/// </summary>
|
||||
internal sealed class X11GLNative : INativeWindow, IDisposable
|
||||
internal sealed class X11GLNative : NativeWindowBase
|
||||
{
|
||||
// TODO: Disable screensaver.
|
||||
// TODO: What happens if we can't disable decorations through motif?
|
||||
|
@ -57,11 +57,6 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
X11WindowInfo window = new X11WindowInfo();
|
||||
|
||||
// Legacy input support
|
||||
X11Input driver;
|
||||
KeyboardDevice keyboard;
|
||||
MouseDevice mouse;
|
||||
|
||||
// Window manager hints for fullscreen windows.
|
||||
// Not used right now (the code is written, but is not 64bit-correct), but could be useful for older WMs which
|
||||
// are not ICCM compliant, but may support MOTIF hints.
|
||||
|
@ -116,6 +111,13 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
bool _decorations_hidden = false;
|
||||
|
||||
// Store previous border and bounds
|
||||
// when switching from WindowState.Normal
|
||||
// to a different state. When switching
|
||||
// back, reset window to these.s
|
||||
WindowBorder _previous_window_border;
|
||||
Size _previous_window_size;
|
||||
|
||||
MouseCursor cursor = MouseCursor.Default;
|
||||
IntPtr cursorHandle;
|
||||
bool cursor_visible = true;
|
||||
|
@ -124,14 +126,14 @@ namespace OpenTK.Platform.X11
|
|||
// Keyboard input
|
||||
readonly byte[] ascii = new byte[16];
|
||||
readonly char[] chars = new char[16];
|
||||
readonly KeyPressEventArgs KPEventArgs = new KeyPressEventArgs('\0');
|
||||
readonly KeyboardKeyEventArgs KeyDownEventArgs = new KeyboardKeyEventArgs();
|
||||
readonly KeyboardKeyEventArgs KeyUpEventArgs = new KeyboardKeyEventArgs();
|
||||
|
||||
readonly IntPtr EmptyCursor;
|
||||
|
||||
public static bool MouseWarpActive = false;
|
||||
|
||||
readonly bool xi2_supported;
|
||||
readonly int xi2_opcode;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
@ -224,15 +226,26 @@ namespace OpenTK.Platform.X11
|
|||
e.ConfigureEvent.height = height;
|
||||
RefreshWindowBounds(ref e);
|
||||
|
||||
driver = new X11Input(window);
|
||||
keyboard = driver.Keyboard[0];
|
||||
mouse = driver.Mouse[0];
|
||||
|
||||
EmptyCursor = CreateEmptyCursor(window);
|
||||
|
||||
Debug.WriteLine(String.Format("X11GLNative window created successfully (id: {0}).", Handle));
|
||||
Debug.Unindent();
|
||||
|
||||
// Request that auto-repeat is only set on devices that support it physically.
|
||||
// This typically means that it's turned off for keyboards (which is what we want).
|
||||
// We prefer this method over XAutoRepeatOff/On, because the latter needs to
|
||||
// be reset before the program exits.
|
||||
bool supported;
|
||||
Functions.XkbSetDetectableAutoRepeat(window.Display, true, out supported);
|
||||
|
||||
// The XInput2 extension makes keyboard and mouse handling much easier.
|
||||
// Check whether it is available.
|
||||
xi2_supported = XI2Mouse.IsSupported(window.Display);
|
||||
if (xi2_supported)
|
||||
{
|
||||
xi2_opcode = XI2Mouse.XIOpCode;
|
||||
}
|
||||
|
||||
exists = true;
|
||||
}
|
||||
|
||||
|
@ -733,7 +746,7 @@ namespace OpenTK.Platform.X11
|
|||
if (Location != new_location)
|
||||
{
|
||||
bounds.Location = new_location;
|
||||
Move(this, EventArgs.Empty);
|
||||
OnMove(EventArgs.Empty);
|
||||
}
|
||||
|
||||
// Note: width and height denote the internal (client) size.
|
||||
|
@ -744,9 +757,15 @@ namespace OpenTK.Platform.X11
|
|||
if (Bounds.Size != new_size)
|
||||
{
|
||||
bounds.Size = new_size;
|
||||
client_rectangle.Size = new Size(e.ConfigureEvent.width, e.ConfigureEvent.height);
|
||||
|
||||
Resize(this, EventArgs.Empty);
|
||||
// X11 sets the client width/height to 0
|
||||
// when the window is minimized. Many apps
|
||||
// do not expect this and crash, so clamp
|
||||
// minimum width/height to 1 instead.
|
||||
client_rectangle.Size = new Size(
|
||||
Math.Max(e.ConfigureEvent.width, 1),
|
||||
Math.Max(e.ConfigureEvent.height, 1));
|
||||
OnResize(EventArgs.Empty);
|
||||
}
|
||||
|
||||
//Debug.Print("[X11] Window bounds changed: {0}", bounds);
|
||||
|
@ -768,25 +787,15 @@ namespace OpenTK.Platform.X11
|
|||
return cursor;
|
||||
}
|
||||
|
||||
static void SetMouseClamped(MouseDevice mouse, int x, int y,
|
||||
int left, int top, int width, int height)
|
||||
{
|
||||
// Clamp mouse to the specified rectangle.
|
||||
x = Math.Max(x, left);
|
||||
x = Math.Min(x, width);
|
||||
y = Math.Max(y, top);
|
||||
y = Math.Min(y, height);
|
||||
mouse.Position = new Point(x, y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INativeWindow Members
|
||||
|
||||
#region ProcessEvents
|
||||
|
||||
public void ProcessEvents()
|
||||
public override void ProcessEvents()
|
||||
{
|
||||
base.ProcessEvents();
|
||||
// Process all pending events
|
||||
while (Exists && window != null)
|
||||
{
|
||||
|
@ -805,7 +814,7 @@ namespace OpenTK.Platform.X11
|
|||
bool previous_visible = visible;
|
||||
visible = true;
|
||||
if (visible != previous_visible)
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
OnVisibleChanged(EventArgs.Empty);
|
||||
}
|
||||
return;
|
||||
|
||||
|
@ -814,7 +823,7 @@ namespace OpenTK.Platform.X11
|
|||
bool previous_visible = visible;
|
||||
visible = false;
|
||||
if (visible != previous_visible)
|
||||
VisibleChanged(this, EventArgs.Empty);
|
||||
OnVisibleChanged(EventArgs.Empty);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -827,7 +836,7 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
Debug.WriteLine("Exit message received.");
|
||||
CancelEventArgs ce = new CancelEventArgs();
|
||||
Closing(this, ce);
|
||||
OnClosing(ce);
|
||||
|
||||
if (!ce.Cancel)
|
||||
{
|
||||
|
@ -848,7 +857,7 @@ namespace OpenTK.Platform.X11
|
|||
Debug.WriteLine("Window destroyed");
|
||||
exists = false;
|
||||
|
||||
Closed(this, EventArgs.Empty);
|
||||
OnClosed(EventArgs.Empty);
|
||||
|
||||
return;
|
||||
|
||||
|
@ -860,26 +869,18 @@ namespace OpenTK.Platform.X11
|
|||
case XEventName.KeyRelease:
|
||||
bool pressed = e.type == XEventName.KeyPress;
|
||||
Key key;
|
||||
if (driver.TranslateKey(ref e.KeyEvent, out key))
|
||||
if (X11KeyMap.TranslateKey(ref e.KeyEvent, out key))
|
||||
{
|
||||
// Update legacy GameWindow.Keyboard API:
|
||||
keyboard.SetKey(key, (uint)e.KeyEvent.keycode, pressed);
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
// Raise KeyDown event
|
||||
KeyDownEventArgs.Key = key;
|
||||
KeyDownEventArgs.ScanCode = (uint)e.KeyEvent.keycode;
|
||||
KeyDownEventArgs.Modifiers = keyboard.GetModifiers();
|
||||
KeyDown(this, KeyDownEventArgs);
|
||||
bool is_repeat = KeyboardState[key];
|
||||
OnKeyDown(key, is_repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Raise KeyUp event
|
||||
KeyUpEventArgs.Key = key;
|
||||
KeyUpEventArgs.ScanCode = (uint)e.KeyEvent.keycode;
|
||||
KeyUpEventArgs.Modifiers = keyboard.GetModifiers();
|
||||
KeyUp(this, KeyUpEventArgs);
|
||||
OnKeyUp(key);
|
||||
}
|
||||
|
||||
if (pressed)
|
||||
|
@ -895,8 +896,7 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
if (!Char.IsControl(chars[i]))
|
||||
{
|
||||
KPEventArgs.KeyChar = chars[i];
|
||||
KeyPress(this, KPEventArgs);
|
||||
OnKeyPress(chars[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -910,7 +910,7 @@ namespace OpenTK.Platform.X11
|
|||
// to the dead center of the window. Fortunately, this situation
|
||||
// is very very uncommon. Todo: Can this be remedied?
|
||||
int x = e.MotionEvent.x;
|
||||
int y =e.MotionEvent.y;
|
||||
int y = e.MotionEvent.y;
|
||||
// TODO: Have offset as a stored field, only update it when the window moves
|
||||
// The middle point cannot be the average of the Bounds.left/right/top/bottom,
|
||||
// because these fields take into account window decoration (borders, etc),
|
||||
|
@ -929,10 +929,9 @@ namespace OpenTK.Platform.X11
|
|||
}
|
||||
else if (!CursorVisible)
|
||||
{
|
||||
SetMouseClamped(mouse,
|
||||
mouse.X + x - mouse_rel_x,
|
||||
mouse.Y + y - mouse_rel_y,
|
||||
0, 0, Width, Height);
|
||||
OnMouseMove(
|
||||
MathHelper.Clamp(MouseState.X + x - mouse_rel_x, 0, Width),
|
||||
MathHelper.Clamp(MouseState.Y + y - mouse_rel_y, 0, Height));
|
||||
mouse_rel_x = x;
|
||||
mouse_rel_y = y;
|
||||
|
||||
|
@ -942,16 +941,42 @@ namespace OpenTK.Platform.X11
|
|||
}
|
||||
else
|
||||
{
|
||||
SetMouseClamped(mouse, x, y, 0, 0, Width, Height);
|
||||
OnMouseMove(
|
||||
MathHelper.Clamp(x, 0, Width),
|
||||
MathHelper.Clamp(y, 0, Height));
|
||||
mouse_rel_x = x;
|
||||
mouse_rel_y = y;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case XEventName.ButtonPress:
|
||||
{
|
||||
int 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)
|
||||
{
|
||||
OnMouseWheel(dx, dy);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XEventName.ButtonRelease:
|
||||
driver.ProcessEvent(ref e);
|
||||
{
|
||||
int dx, dy;
|
||||
MouseButton button = X11KeyMap.TranslateButton(e.ButtonEvent.button, out dx, out dy);
|
||||
|
||||
if (button != MouseButton.LastButton)
|
||||
{
|
||||
OnMouseUp(button);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XEventName.FocusIn:
|
||||
|
@ -959,7 +984,7 @@ namespace OpenTK.Platform.X11
|
|||
bool previous_focus = has_focus;
|
||||
has_focus = true;
|
||||
if (has_focus != previous_focus)
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
OnFocusedChanged(EventArgs.Empty);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -968,19 +993,19 @@ namespace OpenTK.Platform.X11
|
|||
bool previous_focus = has_focus;
|
||||
has_focus = false;
|
||||
if (has_focus != previous_focus)
|
||||
FocusedChanged(this, EventArgs.Empty);
|
||||
OnFocusedChanged(EventArgs.Empty);
|
||||
}
|
||||
break;
|
||||
|
||||
case XEventName.LeaveNotify:
|
||||
if (CursorVisible)
|
||||
{
|
||||
MouseLeave(this, EventArgs.Empty);
|
||||
OnMouseLeave(EventArgs.Empty);
|
||||
}
|
||||
break;
|
||||
|
||||
case XEventName.EnterNotify:
|
||||
MouseEnter(this, EventArgs.Empty);
|
||||
OnMouseEnter(EventArgs.Empty);
|
||||
break;
|
||||
|
||||
case XEventName.MappingNotify:
|
||||
|
@ -995,7 +1020,7 @@ namespace OpenTK.Platform.X11
|
|||
case XEventName.PropertyNotify:
|
||||
if (e.PropertyEvent.atom == _atom_net_wm_state)
|
||||
{
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
OnWindowStateChanged(EventArgs.Empty);
|
||||
}
|
||||
|
||||
//if (e.PropertyEvent.atom == _atom_net_frame_extents)
|
||||
|
@ -1015,7 +1040,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region Bounds
|
||||
|
||||
public Rectangle Bounds
|
||||
public override Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1061,50 +1086,18 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#endregion
|
||||
|
||||
#region Location
|
||||
#region ClientSize
|
||||
|
||||
public Point Location
|
||||
{
|
||||
get { return Bounds.Location; }
|
||||
set
|
||||
{
|
||||
Bounds = new Rectangle(value, Bounds.Size);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Size
|
||||
|
||||
public Size Size
|
||||
{
|
||||
get { return Bounds.Size; }
|
||||
set
|
||||
{
|
||||
Bounds = new Rectangle(Bounds.Location, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ClientRectangle
|
||||
|
||||
public Rectangle ClientRectangle
|
||||
public override Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (client_rectangle.Width == 0)
|
||||
client_rectangle.Width = 1;
|
||||
if (client_rectangle.Height == 0)
|
||||
client_rectangle.Height = 1;
|
||||
return client_rectangle;
|
||||
return client_rectangle.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
Functions.XMoveWindow(window.Display, window.Handle,
|
||||
value.X, value.Y);
|
||||
Functions.XResizeWindow(window.Display, window.Handle,
|
||||
value.Width, value.Height);
|
||||
}
|
||||
|
@ -1114,65 +1107,9 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#endregion
|
||||
|
||||
#region ClientSize
|
||||
|
||||
public Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return ClientRectangle.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientRectangle = new Rectangle(Point.Empty, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Width
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return ClientSize.Width; }
|
||||
set { ClientSize = new Size(value, Height); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Height
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return ClientSize.Height; }
|
||||
set { ClientSize = new Size(Width, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region X
|
||||
|
||||
public int X
|
||||
{
|
||||
get { return Location.X; }
|
||||
set { Location = new Point(value, Y); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Y
|
||||
|
||||
public int Y
|
||||
{
|
||||
get { return Location.Y; }
|
||||
set { Location = new Point(X, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Icon
|
||||
|
||||
public Icon Icon
|
||||
public override Icon Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1238,7 +1175,7 @@ namespace OpenTK.Platform.X11
|
|||
}
|
||||
|
||||
icon = value;
|
||||
IconChanged(this, EventArgs.Empty);
|
||||
OnIconChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1246,7 +1183,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region Focused
|
||||
|
||||
public bool Focused
|
||||
public override bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1258,7 +1195,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region WindowState
|
||||
|
||||
public OpenTK.WindowState WindowState
|
||||
public override OpenTK.WindowState WindowState
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1319,75 +1256,105 @@ namespace OpenTK.Platform.X11
|
|||
{
|
||||
OpenTK.WindowState current_state = this.WindowState;
|
||||
|
||||
// When switching away from normal state, store
|
||||
// the "normal" border and size. These will be used
|
||||
// for restoring to normal state.
|
||||
if (current_state == OpenTK.WindowState.Normal)
|
||||
{
|
||||
_previous_window_border = WindowBorder;
|
||||
_previous_window_size = ClientSize;
|
||||
}
|
||||
|
||||
if (current_state == value)
|
||||
return;
|
||||
|
||||
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.Handle.ToString(),
|
||||
current_state.ToString(), value.ToString());
|
||||
current_state.ToString(), value.ToString());
|
||||
|
||||
using (new XLock(window.Display))
|
||||
// When minimizing the window, call XIconifyWindow and bail out.
|
||||
// For other states, we first need to restore the window, set the
|
||||
// new state and reset the window border and bounds.
|
||||
if (value != OpenTK.WindowState.Minimized)
|
||||
{
|
||||
// Reset the current window state
|
||||
if (current_state == OpenTK.WindowState.Minimized)
|
||||
Functions.XMapWindow(window.Display, window.Handle);
|
||||
else if (current_state == OpenTK.WindowState.Fullscreen)
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove,
|
||||
_atom_net_wm_state_fullscreen,
|
||||
IntPtr.Zero);
|
||||
else if (current_state == OpenTK.WindowState.Maximized)
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
|
||||
Functions.XSync(window.Display, false);
|
||||
}
|
||||
// We can't resize the window if its border is fixed, so make it resizable first.
|
||||
bool temporary_resizable = false;
|
||||
WindowBorder previous_state = WindowBorder;
|
||||
if (WindowBorder != WindowBorder.Resizable)
|
||||
{
|
||||
temporary_resizable = true;
|
||||
WindowBorder = WindowBorder.Resizable;
|
||||
}
|
||||
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (value)
|
||||
// Some WMs cannot switch between specific states directly,
|
||||
// Switch back to a regular window first.
|
||||
if (WindowBorder == WindowBorder.Fixed)
|
||||
{
|
||||
ChangeWindowBorder(WindowBorder.Resizable);
|
||||
}
|
||||
|
||||
ResetWindowState(current_state);
|
||||
}
|
||||
|
||||
// Change to the desired WindowState.
|
||||
// Note that OnWindowStateChanged is called inside
|
||||
// ProcessEvents.
|
||||
ChangeWindowState(value);
|
||||
ProcessEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void ResetWindowState(OpenTK.WindowState current_state)
|
||||
{
|
||||
if (current_state != OpenTK.WindowState.Normal)
|
||||
{
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (current_state)
|
||||
{
|
||||
case OpenTK.WindowState.Normal:
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Minimized:
|
||||
// Todo: multiscreen support
|
||||
Functions.XIconifyWindow(window.Display, window.Handle, window.Screen);
|
||||
|
||||
Functions.XMapWindow(window.Display, window.Handle);
|
||||
break;
|
||||
|
||||
|
||||
case OpenTK.WindowState.Fullscreen:
|
||||
//_previous_window_border = this.WindowBorder;
|
||||
//this.WindowBorder = WindowBorder.Hidden;
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
|
||||
Functions.SendNetWMMessage(window,
|
||||
_atom_net_wm_state,
|
||||
_atom_remove,
|
||||
_atom_net_wm_state_fullscreen,
|
||||
IntPtr.Zero);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window,
|
||||
_atom_net_wm_state,
|
||||
_atom_toggle,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (temporary_resizable)
|
||||
WindowBorder = previous_state;
|
||||
void ChangeWindowState(OpenTK.WindowState value)
|
||||
{
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case OpenTK.WindowState.Normal:
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
ChangeWindowBorder(_previous_window_border,
|
||||
_previous_window_size.Width, _previous_window_size.Height);
|
||||
break;
|
||||
|
||||
ProcessEvents();
|
||||
case OpenTK.WindowState.Maximized:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_maximized_horizontal,
|
||||
_atom_net_wm_state_maximized_vertical);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Minimized:
|
||||
Functions.XIconifyWindow(window.Display, window.Handle, window.Screen);
|
||||
break;
|
||||
|
||||
case OpenTK.WindowState.Fullscreen:
|
||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
||||
Functions.XRaiseWindow(window.Display, window.Handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1395,77 +1362,76 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region WindowBorder
|
||||
|
||||
public OpenTK.WindowBorder WindowBorder
|
||||
public override OpenTK.WindowBorder WindowBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsWindowBorderHidden)
|
||||
if (IsWindowBorderHidden || WindowState == OpenTK.WindowState.Fullscreen)
|
||||
return WindowBorder.Hidden;
|
||||
|
||||
if (IsWindowBorderResizable)
|
||||
return WindowBorder.Resizable;
|
||||
else
|
||||
else if (!IsWindowBorderResizable)
|
||||
return WindowBorder.Fixed;
|
||||
else if (WindowState == OpenTK.WindowState.Maximized)
|
||||
return _previous_window_border;
|
||||
else
|
||||
return WindowBorder.Resizable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (WindowBorder == value)
|
||||
return;
|
||||
|
||||
if (WindowBorder == WindowBorder.Hidden)
|
||||
EnableWindowDecorations();
|
||||
|
||||
switch (value)
|
||||
// We cannot change the border of a fullscreen window.
|
||||
// Record the new value and set it on the next WindowState
|
||||
// change.
|
||||
if (WindowState == OpenTK.WindowState.Fullscreen)
|
||||
{
|
||||
case WindowBorder.Fixed:
|
||||
Debug.Print("Making WindowBorder fixed.");
|
||||
SetWindowMinMax((short)Width, (short)Height, (short)Width, (short)Height);
|
||||
|
||||
break;
|
||||
|
||||
case WindowBorder.Resizable:
|
||||
Debug.Print("Making WindowBorder resizable.");
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
|
||||
break;
|
||||
|
||||
case WindowBorder.Hidden:
|
||||
Debug.Print("Making WindowBorder hidden.");
|
||||
DisableWindowDecorations();
|
||||
|
||||
break;
|
||||
_previous_window_border = value;
|
||||
return;
|
||||
}
|
||||
|
||||
WindowBorderChanged(this, EventArgs.Empty);
|
||||
ChangeWindowBorder(value);
|
||||
OnWindowBorderChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeWindowBorder(WindowBorder value)
|
||||
{
|
||||
ChangeWindowBorder(value, Width, Height);
|
||||
}
|
||||
|
||||
void ChangeWindowBorder(WindowBorder value, int width, int height)
|
||||
{
|
||||
if (WindowBorder == WindowBorder.Hidden)
|
||||
EnableWindowDecorations();
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case WindowBorder.Fixed:
|
||||
Debug.Print("Making WindowBorder fixed.");
|
||||
SetWindowMinMax((short)width, (short)height, (short)width, (short)height);
|
||||
break;
|
||||
case WindowBorder.Resizable:
|
||||
Debug.Print("Making WindowBorder resizable.");
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
break;
|
||||
case WindowBorder.Hidden:
|
||||
Debug.Print("Making WindowBorder hidden.");
|
||||
// Make the hidden border resizable, otherwise
|
||||
// we won't be able to maximize the window or
|
||||
// enter fullscreen mode.
|
||||
SetWindowMinMax(_min_width, _min_height, -1, -1);
|
||||
DisableWindowDecorations();
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessEvents();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<EventArgs> Move = delegate { };
|
||||
public event EventHandler<EventArgs> Resize = delegate { };
|
||||
public event EventHandler<System.ComponentModel.CancelEventArgs> Closing = delegate { };
|
||||
public event EventHandler<EventArgs> Closed = delegate { };
|
||||
public event EventHandler<EventArgs> Disposed = delegate { };
|
||||
public event EventHandler<EventArgs> IconChanged = delegate { };
|
||||
public event EventHandler<EventArgs> TitleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> VisibleChanged = delegate { };
|
||||
public event EventHandler<EventArgs> FocusedChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
|
||||
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
|
||||
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
|
||||
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
|
||||
public event EventHandler<EventArgs> MouseEnter = delegate { };
|
||||
public event EventHandler<EventArgs> MouseLeave = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cursor
|
||||
|
||||
public MouseCursor Cursor
|
||||
public override MouseCursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1505,7 +1471,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region CursorVisible
|
||||
|
||||
public bool CursorVisible
|
||||
public override bool CursorVisible
|
||||
{
|
||||
get { return cursor_visible; }
|
||||
set
|
||||
|
@ -1535,24 +1501,12 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region --- INativeGLWindow Members ---
|
||||
|
||||
#region public IInputDriver InputDriver
|
||||
|
||||
public IInputDriver InputDriver
|
||||
{
|
||||
get
|
||||
{
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public bool Exists
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a render window/context exists.
|
||||
/// </summary>
|
||||
public bool Exists
|
||||
public override bool Exists
|
||||
{
|
||||
get { return exists; }
|
||||
}
|
||||
|
@ -1586,7 +1540,7 @@ namespace OpenTK.Platform.X11
|
|||
/// TODO: Use atoms for this property.
|
||||
/// Gets or sets the GameWindow title.
|
||||
/// </summary>
|
||||
public string Title
|
||||
public override string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1610,7 +1564,7 @@ namespace OpenTK.Platform.X11
|
|||
}
|
||||
}
|
||||
|
||||
TitleChanged(this, EventArgs.Empty);
|
||||
OnTitleChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1618,7 +1572,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region public bool Visible
|
||||
|
||||
public bool Visible
|
||||
public override bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1647,14 +1601,14 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region public IWindowInfo WindowInfo
|
||||
|
||||
public IWindowInfo WindowInfo
|
||||
public override IWindowInfo WindowInfo
|
||||
{
|
||||
get { return window; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Close() { Exit(); }
|
||||
public override void Close() { Exit(); }
|
||||
|
||||
#region public void Exit()
|
||||
|
||||
|
@ -1691,7 +1645,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region PointToClient
|
||||
|
||||
public Point PointToClient(Point point)
|
||||
public override Point PointToClient(Point point)
|
||||
{
|
||||
int ox, oy;
|
||||
IntPtr child;
|
||||
|
@ -1711,7 +1665,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region PointToScreen
|
||||
|
||||
public Point PointToScreen(Point point)
|
||||
public override Point PointToScreen(Point point)
|
||||
{
|
||||
int ox, oy;
|
||||
IntPtr child;
|
||||
|
@ -1733,13 +1687,7 @@ namespace OpenTK.Platform.X11
|
|||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool manuallyCalled)
|
||||
protected override void Dispose(bool manuallyCalled)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
|
@ -1775,11 +1723,6 @@ namespace OpenTK.Platform.X11
|
|||
}
|
||||
}
|
||||
|
||||
~X11GLNative()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if !MINIMAL
|
||||
using System.Drawing;
|
||||
#endif
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace OpenTK.Platform.X11
|
||||
{
|
||||
/// \internal
|
||||
/// <summary>
|
||||
/// Drives the InputDriver on X11.
|
||||
/// This class supports OpenTK, and is not intended for users of OpenTK.
|
||||
/// </summary>
|
||||
internal sealed class X11Input : IInputDriver
|
||||
{
|
||||
KeyboardDevice keyboard = new KeyboardDevice();
|
||||
MouseDevice mouse = new MouseDevice();
|
||||
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
|
||||
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(1);
|
||||
|
||||
int firstKeyCode, lastKeyCode; // The smallest and largest KeyCode supported by the X server.
|
||||
int keysyms_per_keycode; // The number of KeySyms for each KeyCode.
|
||||
IntPtr[] keysyms;
|
||||
|
||||
//bool disposed;
|
||||
|
||||
#region --- Constructors ---
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new X11Input driver. Creates a hidden InputOnly window, child to
|
||||
/// the main application window, which selects input events and routes them to
|
||||
/// the device specific drivers (Keyboard, Mouse, Hid).
|
||||
/// </summary>
|
||||
/// <param name="attach">The window which the InputDriver will attach itself on.</param>
|
||||
public X11Input(IWindowInfo attach)
|
||||
{
|
||||
Debug.WriteLine("Initalizing X11 input driver.");
|
||||
Debug.Indent();
|
||||
|
||||
if (attach == null)
|
||||
throw new ArgumentException("A valid parent window must be defined, in order to create an X11Input driver.");
|
||||
|
||||
//window = new X11WindowInfo(attach);
|
||||
X11WindowInfo window = (X11WindowInfo)attach;
|
||||
|
||||
// Init mouse
|
||||
mouse.Description = "Default X11 mouse";
|
||||
mouse.DeviceID = IntPtr.Zero;
|
||||
mouse.NumberOfButtons = 5;
|
||||
mouse.NumberOfWheels = 1;
|
||||
dummy_mice_list.Add(mouse);
|
||||
|
||||
using (new XLock(window.Display))
|
||||
{
|
||||
// Init keyboard
|
||||
API.DisplayKeycodes(window.Display, ref firstKeyCode, ref lastKeyCode);
|
||||
Debug.Print("First keycode: {0}, last {1}", firstKeyCode, lastKeyCode);
|
||||
|
||||
IntPtr keysym_ptr = API.GetKeyboardMapping(window.Display, (byte)firstKeyCode,
|
||||
lastKeyCode - firstKeyCode + 1, ref keysyms_per_keycode);
|
||||
Debug.Print("{0} keysyms per keycode.", keysyms_per_keycode);
|
||||
|
||||
keysyms = new IntPtr[(lastKeyCode - firstKeyCode + 1) * keysyms_per_keycode];
|
||||
Marshal.PtrToStructure(keysym_ptr, keysyms);
|
||||
API.Free(keysym_ptr);
|
||||
|
||||
keyboard.Description = "Default X11 keyboard";
|
||||
keyboard.NumberOfKeys = lastKeyCode - firstKeyCode + 1;
|
||||
keyboard.DeviceID = IntPtr.Zero;
|
||||
dummy_keyboard_list.Add(keyboard);
|
||||
|
||||
// Request that auto-repeat is only set on devices that support it physically.
|
||||
// This typically means that it's turned off for keyboards (which is what we want).
|
||||
// We prefer this method over XAutoRepeatOff/On, because the latter needs to
|
||||
// be reset before the program exits.
|
||||
bool supported;
|
||||
Functions.XkbSetDetectableAutoRepeat(window.Display, true, out supported);
|
||||
}
|
||||
|
||||
Debug.Unindent();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TranslateKey
|
||||
|
||||
internal bool TranslateKey(ref XKeyEvent e, out Key key)
|
||||
{
|
||||
XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
|
||||
XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
|
||||
key = X11KeyMap.GetKey(keysym);
|
||||
if (key == Key.Unknown)
|
||||
{
|
||||
key = X11KeyMap.GetKey(keysym2);
|
||||
}
|
||||
if (key == Key.Unknown)
|
||||
{
|
||||
Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
|
||||
}
|
||||
|
||||
return key != Key.Unknown;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region internal void ProcessEvent(ref XEvent e)
|
||||
|
||||
internal void ProcessEvent(ref XEvent e)
|
||||
{
|
||||
switch (e.type)
|
||||
{
|
||||
case XEventName.ButtonPress:
|
||||
if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = true;
|
||||
else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = true;
|
||||
else if (e.ButtonEvent.button == 3) mouse[OpenTK.Input.MouseButton.Right] = true;
|
||||
else if (e.ButtonEvent.button == 4) mouse.Wheel++;
|
||||
else if (e.ButtonEvent.button == 5) mouse.Wheel--;
|
||||
else if (e.ButtonEvent.button == 6) mouse[OpenTK.Input.MouseButton.Button1] = true;
|
||||
else if (e.ButtonEvent.button == 7) mouse[OpenTK.Input.MouseButton.Button2] = true;
|
||||
else if (e.ButtonEvent.button == 8) mouse[OpenTK.Input.MouseButton.Button3] = true;
|
||||
else if (e.ButtonEvent.button == 9) mouse[OpenTK.Input.MouseButton.Button4] = true;
|
||||
else if (e.ButtonEvent.button == 10) mouse[OpenTK.Input.MouseButton.Button5] = true;
|
||||
else if (e.ButtonEvent.button == 11) mouse[OpenTK.Input.MouseButton.Button6] = true;
|
||||
else if (e.ButtonEvent.button == 12) mouse[OpenTK.Input.MouseButton.Button7] = true;
|
||||
else if (e.ButtonEvent.button == 13) mouse[OpenTK.Input.MouseButton.Button8] = true;
|
||||
else if (e.ButtonEvent.button == 14) mouse[OpenTK.Input.MouseButton.Button9] = true;
|
||||
//if ((e.state & (int)X11.MouseMask.Button4Mask) != 0) m.Wheel++;
|
||||
//if ((e.state & (int)X11.MouseMask.Button5Mask) != 0) m.Wheel--;
|
||||
//Debug.Print("Button pressed: {0}", e.ButtonEvent.button);
|
||||
break;
|
||||
|
||||
case XEventName.ButtonRelease:
|
||||
if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = false;
|
||||
else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = false;
|
||||
else if (e.ButtonEvent.button == 3) mouse[OpenTK.Input.MouseButton.Right] = false;
|
||||
else if (e.ButtonEvent.button == 6) mouse[OpenTK.Input.MouseButton.Button1] = false;
|
||||
else if (e.ButtonEvent.button == 7) mouse[OpenTK.Input.MouseButton.Button2] = false;
|
||||
else if (e.ButtonEvent.button == 8) mouse[OpenTK.Input.MouseButton.Button3] = false;
|
||||
else if (e.ButtonEvent.button == 9) mouse[OpenTK.Input.MouseButton.Button4] = false;
|
||||
else if (e.ButtonEvent.button == 10) mouse[OpenTK.Input.MouseButton.Button5] = false;
|
||||
else if (e.ButtonEvent.button == 11) mouse[OpenTK.Input.MouseButton.Button6] = false;
|
||||
else if (e.ButtonEvent.button == 12) mouse[OpenTK.Input.MouseButton.Button7] = false;
|
||||
else if (e.ButtonEvent.button == 13) mouse[OpenTK.Input.MouseButton.Button8] = false;
|
||||
else if (e.ButtonEvent.button == 14) mouse[OpenTK.Input.MouseButton.Button9] = false;
|
||||
break;
|
||||
|
||||
case XEventName.MotionNotify:
|
||||
mouse.Position = new Point(e.MotionEvent.x, e.MotionEvent.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IInputDriver Members ---
|
||||
|
||||
#region public IList<Keyboard> Keyboard
|
||||
|
||||
public IList<KeyboardDevice> Keyboard
|
||||
{
|
||||
get { return dummy_keyboard_list; }//return keyboardDriver.Keyboard;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public IList<Mouse> Mouse
|
||||
|
||||
public IList<MouseDevice> Mouse
|
||||
{
|
||||
get { return (IList<MouseDevice>)dummy_mice_list; } //return mouseDriver.Mouse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IList<JoystickDevice> Joysticks
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public void Poll()
|
||||
|
||||
/// <summary>
|
||||
/// Polls and updates state of all keyboard, mouse and joystick devices.
|
||||
/// </summary>
|
||||
public void Poll()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IDisposable Members ---
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//this.Dispose(true);
|
||||
//GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
//private void Dispose(bool manual)
|
||||
//{
|
||||
// if (!disposed)
|
||||
// {
|
||||
// //disposing = true;
|
||||
// if (pollingThread != null && pollingThread.IsAlive)
|
||||
// pollingThread.Abort();
|
||||
|
||||
// if (manual)
|
||||
// {
|
||||
// }
|
||||
|
||||
// disposed = true;
|
||||
// }
|
||||
//}
|
||||
|
||||
//~X11Input()
|
||||
//{
|
||||
// this.Dispose(false);
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -370,5 +370,47 @@ namespace OpenTK.Platform.X11
|
|||
return Key.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool TranslateKey(ref XKeyEvent e, out Key key)
|
||||
{
|
||||
XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
|
||||
XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
|
||||
key = X11KeyMap.GetKey(keysym);
|
||||
if (key == Key.Unknown)
|
||||
{
|
||||
key = X11KeyMap.GetKey(keysym2);
|
||||
}
|
||||
if (key == Key.Unknown)
|
||||
{
|
||||
Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
|
||||
}
|
||||
|
||||
return key != Key.Unknown;
|
||||
}
|
||||
|
||||
internal static MouseButton TranslateButton(int button, out int wheelx, out int wheely)
|
||||
{
|
||||
wheelx = 0;
|
||||
wheely = 0;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case 1: return MouseButton.Left;
|
||||
case 2: return MouseButton.Middle;
|
||||
case 3: return MouseButton.Right;
|
||||
case 4: wheely = +1; return MouseButton.LastButton;
|
||||
case 5: wheely = -1; return MouseButton.LastButton;
|
||||
case 6: wheelx = +1; return MouseButton.LastButton;
|
||||
case 7: wheelx = -1; return MouseButton.LastButton;
|
||||
case 8: return MouseButton.Button1;
|
||||
case 9: return MouseButton.Button2;
|
||||
case 10: return MouseButton.Button3;
|
||||
case 11: return MouseButton.Button4;
|
||||
case 12: return MouseButton.Button5;
|
||||
case 13: return MouseButton.Button6;
|
||||
case 14: return MouseButton.Button7;
|
||||
default: return MouseButton.LastButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ namespace OpenTK.Platform.X11
|
|||
List<MouseState> mice = new List<MouseState>();
|
||||
Dictionary<int, int> rawids = new Dictionary<int, int>(); // maps raw ids to mouse ids
|
||||
internal readonly X11WindowInfo window;
|
||||
static int XIOpCode;
|
||||
internal static int XIOpCode { get; private set; }
|
||||
static bool supported;
|
||||
|
||||
static readonly Functions.EventPredicate PredicateImpl = IsEventValid;
|
||||
readonly IntPtr Predicate = Marshal.GetFunctionPointerForDelegate(PredicateImpl);
|
||||
|
@ -204,8 +205,8 @@ namespace OpenTK.Platform.X11
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue