225 lines
8.9 KiB
C#
225 lines
8.9 KiB
C#
using System.Diagnostics;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using Dashboard.Events;
|
|
using Dashboard.OpenGL;
|
|
using Dashboard.Pal;
|
|
using Dashboard.Windowing;
|
|
using OpenTK.Platform;
|
|
using TK = OpenTK.Platform.Toolkit;
|
|
using OPENTK = OpenTK.Platform;
|
|
using DB = Dashboard.Events;
|
|
|
|
namespace Dashboard.OpenTK.PAL2
|
|
{
|
|
public class Pal2Application : Application
|
|
{
|
|
public override string DriverName => "Dashboard OpenTK PAL2.0 Driver";
|
|
public override string DriverVendor => "Dashboard";
|
|
public override Version DriverVersion => new Version(0, 1);
|
|
public GraphicsApiHints GraphicsApiHints { get; set; } = new OpenGLGraphicsApiHints();
|
|
|
|
private readonly List<PhysicalWindow> _windows = new List<PhysicalWindow>();
|
|
|
|
private readonly ConditionalWeakTable<WindowHandle, WindowExtraInfo> _windowHandleWindowMap =
|
|
new ConditionalWeakTable<WindowHandle, WindowExtraInfo>();
|
|
|
|
private long _tick = Stopwatch.GetTimestamp();
|
|
|
|
public override IPhysicalWindow CreatePhysicalWindow()
|
|
{
|
|
PhysicalWindow window = new PhysicalWindow(this, GraphicsApiHints);
|
|
|
|
_windows.Add(window);
|
|
_windowHandleWindowMap.Add(window.WindowHandle, new WindowExtraInfo(window));
|
|
|
|
return window;
|
|
}
|
|
|
|
public override IWindow CreateWindow()
|
|
{
|
|
return CreatePhysicalWindow();
|
|
}
|
|
|
|
protected override void InitializeInternal()
|
|
{
|
|
base.InitializeInternal();
|
|
|
|
EventQueue.EventRaised += OnEventRaised;
|
|
}
|
|
|
|
public override void RunEvents(bool wait)
|
|
{
|
|
TK.Window.ProcessEvents(wait);
|
|
|
|
long tock = Stopwatch.GetTimestamp();
|
|
long elapsed = _tick - tock;
|
|
float delta = (float)elapsed / Stopwatch.Frequency;
|
|
TickEventArgs tickEvent = new TickEventArgs(delta);
|
|
|
|
_tick = tock;
|
|
|
|
for (int i = 0; i < _windows.Count; i++)
|
|
{
|
|
PhysicalWindow window = _windows[i];
|
|
|
|
if (window.IsDisposed)
|
|
{
|
|
_windows.RemoveAt(i);
|
|
continue;
|
|
}
|
|
|
|
window.SendEvent(this, tickEvent);
|
|
window.SendEvent(this, new PaintEventArgs(window.DeviceContext));
|
|
// For now we swap each window individually.
|
|
((GLDeviceContext)window.DeviceContext).GLContext.SwapGroup.Swap();
|
|
}
|
|
}
|
|
|
|
private void OnEventRaised(PalHandle? handle, PlatformEventType type, EventArgs args)
|
|
{
|
|
if (handle is WindowHandle window)
|
|
{
|
|
OnWindowEventRaised(window, type, args);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
System.Diagnostics.Debugger.Break();
|
|
}
|
|
}
|
|
|
|
private void OnWindowEventRaised(WindowHandle handle, PlatformEventType type, EventArgs args)
|
|
{
|
|
if (!_windowHandleWindowMap.TryGetValue(handle, out WindowExtraInfo? info))
|
|
{
|
|
Debugger?.LogDebug($"Unknown window handle {handle} received from OpenTK.");
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case PlatformEventType.MouseDown:
|
|
{
|
|
MouseButtonDownEventArgs down = (MouseButtonDownEventArgs)args;
|
|
MouseButtons buttons = (MouseButtons)(1 << (int)down.Button);
|
|
ModifierKeys modifierKeys = GetModifierKeys(down.Modifiers);
|
|
// TODO: modifier keys
|
|
MouseButtonEventArgs down2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, false);
|
|
info.Window.SendEvent(this, down2);
|
|
break;
|
|
}
|
|
case PlatformEventType.MouseUp:
|
|
{
|
|
MouseButtonUpEventArgs up = (MouseButtonUpEventArgs)args;
|
|
MouseButtons buttons = (MouseButtons)(1 << (int)up.Button);
|
|
ModifierKeys modifierKeys = GetModifierKeys(up.Modifiers);
|
|
// TODO: modifier keys
|
|
MouseButtonEventArgs up2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, true);
|
|
info.Window.SendEvent(this, up2);
|
|
break;
|
|
}
|
|
case PlatformEventType.MouseMove:
|
|
{
|
|
OPENTK.MouseMoveEventArgs move = (OPENTK.MouseMoveEventArgs)args;
|
|
Vector2 position = new Vector2(move.ClientPosition.X, move.ClientPosition.Y);
|
|
DB.MouseMoveEventArgs move2 = new DB.MouseMoveEventArgs(position, position - info.MousePosition);
|
|
|
|
info.MousePosition = position;
|
|
|
|
info.Window.SendEvent(this, move2);
|
|
break;
|
|
}
|
|
case PlatformEventType.Scroll:
|
|
{
|
|
ScrollEventArgs scroll = (ScrollEventArgs)args;
|
|
Vector2 distance = new Vector2(scroll.Distance.X, scroll.Distance.Y);
|
|
Vector2 delta = new Vector2(scroll.Delta.X, scroll.Delta.Y);
|
|
MouseScrollEventArgs scroll2 = new MouseScrollEventArgs(distance, delta);
|
|
info.Window.SendEvent(this, scroll2);
|
|
break;
|
|
}
|
|
case PlatformEventType.KeyDown:
|
|
{
|
|
KeyDownEventArgs down = (KeyDownEventArgs)args;
|
|
|
|
ModifierKeys modifierKeys = GetModifierKeys(down.Modifiers);
|
|
KeyCode keyCode = GetKeyCode(down.Key);
|
|
ScanCode scanCode = GetScanCode(down.Scancode);
|
|
|
|
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, false);
|
|
info.Window.SendEvent(this, up2);
|
|
break;
|
|
}
|
|
case PlatformEventType.KeyUp:
|
|
{
|
|
KeyUpEventArgs up = (KeyUpEventArgs)args;
|
|
|
|
ModifierKeys modifierKeys = GetModifierKeys(up.Modifiers);
|
|
KeyCode keyCode = GetKeyCode(up.Key);
|
|
ScanCode scanCode = GetScanCode(up.Scancode);
|
|
|
|
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, true);
|
|
info.Window.SendEvent(this, up2);
|
|
break;
|
|
}
|
|
case PlatformEventType.Close:
|
|
{
|
|
info.Window.SendEvent(this, new WindowCloseEvent());
|
|
break;
|
|
}
|
|
default:
|
|
Debugger?.LogDebug($"Unknown event type {type} with \"{args}\".");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static ModifierKeys GetModifierKeys(KeyModifier modifier)
|
|
{
|
|
ModifierKeys keys = 0;
|
|
|
|
keys |= modifier.HasFlag(KeyModifier.NumLock) ? ModifierKeys.NumLock : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.CapsLock) ? ModifierKeys.CapsLock : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.ScrollLock) ? ModifierKeys.ScrollLock : 0;
|
|
|
|
keys |= modifier.HasFlag(KeyModifier.LeftShift) ? ModifierKeys.LeftShift : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.LeftControl) ? ModifierKeys.LeftControl : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.LeftAlt) ? ModifierKeys.LeftAlt : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.LeftGUI) ? ModifierKeys.LeftMeta : 0;
|
|
|
|
keys |= modifier.HasFlag(KeyModifier.RightShift) ? ModifierKeys.RightShift : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.RightControl) ? ModifierKeys.RightControl : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.RightAlt) ? ModifierKeys.RightAlt : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.RightGUI) ? ModifierKeys.RightMeta : 0;
|
|
|
|
keys |= modifier.HasFlag(KeyModifier.Shift) ? ModifierKeys.Shift : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.Control) ? ModifierKeys.Control : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.Alt) ? ModifierKeys.Alt : 0;
|
|
keys |= modifier.HasFlag(KeyModifier.GUI) ? ModifierKeys.Meta : 0;
|
|
|
|
// C# makes this cast as annoying as possible.
|
|
keys |= (ModifierKeys)((((int)keys >> (int)ModifierKeys.RightBitPos) & 0xF) |
|
|
(((int)keys >> (int)ModifierKeys.LeftBitPos) & 0xF));
|
|
|
|
return keys;
|
|
}
|
|
|
|
private record WindowExtraInfo(PhysicalWindow Window)
|
|
{
|
|
public Vector2 MousePosition { get; set; } = Vector2.Zero;
|
|
}
|
|
|
|
// TODO: Keycode and scancode tables.
|
|
|
|
private static KeyCode GetKeyCode(Key key) => key switch
|
|
{
|
|
_ => (KeyCode)0,
|
|
};
|
|
|
|
private static ScanCode GetScanCode(Scancode scanCode) => scanCode switch
|
|
{
|
|
_ => (ScanCode)0,
|
|
};
|
|
}
|
|
}
|