Major updates to shutdown sequence (should correct bug where GameWindow hangs on exit). Enhanced the IGameWindow interface by adding the Keyboard and IsExiting properties.

Fully implemented keyboard on X11. Renamed some OpenTK keys.
This commit is contained in:
the_fiddler 2007-08-06 09:22:04 +00:00
parent 94e738bb9a
commit f30e7f6df8
9 changed files with 157 additions and 159 deletions

View file

@ -10,6 +10,8 @@ using System.Text;
using System.Diagnostics;
using OpenTK.Platform;
using OpenTK.Input;
using System.Threading;
namespace OpenTK
{
@ -23,6 +25,9 @@ namespace OpenTK
private InputDriver driver;
private bool isExiting;
private bool disposed;
#endregion
#region --- Contructors ---
@ -70,38 +75,10 @@ namespace OpenTK
#endregion
#region --- Public Properties ---
#region public IList<Input.Keyboard> Keyboard
/// <summary>
/// Gets the list of available Keyboard devices.
/// </summary>
public IList<Input.Keyboard> Keyboard
{
get
{
return InputDriver.Keyboard;
}
}
#endregion
#region --- Internal Properties ---
#region public IList<OpenTK.Input.IInputDevice> Input
/// <summary>
/// Gets the list of available InputDevices.
/// </summary>
public IList<OpenTK.Input.IInputDevice> Input
{
get
{
return InputDriver.InputDevices;
}
}
#endregion
internal InputDriver InputDriver
{
get
@ -117,6 +94,8 @@ namespace OpenTK
#endregion
#endregion
#region --- INativeGLWindow Members ---
#region public void CreateWindow(DisplayMode mode)
@ -128,7 +107,7 @@ namespace OpenTK
/// <exception cref="ApplicationException">Occurs when a render window already exists.</exception>
public void CreateWindow(DisplayMode mode)
{
if (!Created)
if (!Exists)
{
glWindow.CreateWindow(mode);
}
@ -144,10 +123,15 @@ namespace OpenTK
/// <summary>
/// Gracefully exits the current GameWindow.
/// Override if you want to provide yor own exit sequence.
/// If you override this method, place a call to base.Exit(), to ensure
/// proper OpenTK shutdown.
/// </summary>
public void Exit()
public virtual void Exit()
{
glWindow.Exit();
isExiting = true;
//glWindow.Exit();
//this.Dispose();
}
#endregion
@ -202,7 +186,7 @@ namespace OpenTK
{
get
{
if (!glWindow.Created)
if (!glWindow.Exists)
{
Debug.WriteLine("WARNING: OpenGL Context accessed before creating a render window. This may indicate a programming error. Force-creating a render window.");
mode = new DisplayMode(640, 480);
@ -214,14 +198,14 @@ namespace OpenTK
#endregion
#region public bool Created
#region public bool Exists
/// <summary>
/// Gets a value indicating whether a render window has been created.
/// Gets a value indicating whether a render window has been exists.
/// </summary>
public bool Created
public bool Exists
{
get { return glWindow.Created; }
get { return glWindow.Exists; }
}
#endregion
@ -258,12 +242,18 @@ namespace OpenTK
/// </remarks>
public virtual void Run()
{
while (!this.Quit)
while (!this.Quit && !IsExiting)
{
this.ProcessEvents();
this.OnUpdateFrame();
this.OnRenderFrame();
}
glWindow.Exit();
while (glWindow.Exists)
{
this.ProcessEvents();
}
}
#endregion
@ -315,7 +305,7 @@ namespace OpenTK
/// </remarks>
public virtual void OnRenderFrame()
{
if (!this.Created)
if (!this.Exists)
{
Debug.Print("WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window.");
mode = new DisplayMode(640, 480);
@ -338,7 +328,7 @@ namespace OpenTK
/// </remarks>
public virtual void OnUpdateFrame()
{
if (!this.Created)
if (!this.Exists)
{
Debug.Print("WARNING: UpdateFrame event raised, without a valid render window. This may indicate a programming error. Creating render window.");
mode = new DisplayMode(640, 480);
@ -360,6 +350,36 @@ namespace OpenTK
/// </summary>
public event RenderFrameEvent RenderFrame;
#region public bool IsExiting
/// <summary>
/// Gets a value indicating whether the shutdown sequence has been initiated
/// for this window, by calling GameWindow.Exit() or hitting the 'close' button.
/// If this property is true, it is no longer safe to use any OpenTK.Input or
/// OpenTK.OpenGL functions or properties.
/// </summary>
public bool IsExiting
{
get { return isExiting; }
}
#endregion
#region public IList<Keyboard> Keyboard
/// <summary>
/// Gets the list of available Keyboard devices.
/// </summary>
public IList<Keyboard> Keyboard
{
get
{
return InputDriver.Keyboard;
}
}
#endregion
#endregion
#region --- IResizable Members ---
@ -438,8 +458,32 @@ namespace OpenTK
public void Dispose()
{
glWindow.Dispose();
glWindow = null;
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
{
// Is this safe? Maybe 'Debug' has been disposed, too...
Debug.Print("{0} disposing GameWindow.", manual ? "Manually" : "Automatically");
if (manual)
{
if (glWindow != null)
{
glWindow.Dispose();
glWindow = null;
}
}
disposed = true;
}
}
~GameWindow()
{
Dispose(false);
}
#endregion

View file

@ -141,7 +141,7 @@ namespace OpenTK.Input
Escape,
Space,
Tab,
Backspace,
BackSpace,
Insert,
Delete,
PageUp,

View file

@ -14,6 +14,9 @@ namespace OpenTK.Platform
event UpdateFrameEvent UpdateFrame;
event RenderFrameEvent RenderFrame;
bool IsExiting { get; }
IList<OpenTK.Input.Keyboard> Keyboard { get; }
}
public delegate void UpdateFrameEvent(EventArgs e);

View file

@ -13,7 +13,7 @@ namespace OpenTK.Platform
void ProcessEvents();
void Exit();
bool Created { get; }
bool Exists { get; }
bool Quit { get; }
IWindowInfo WindowInfo { get; }
}

View file

@ -31,7 +31,7 @@ namespace OpenTK.Platform.Windows
private bool fullscreen = false;
private bool disposed;
private bool quit;
private bool created;
private bool exists;
private WindowInfo info;
#endregion
@ -94,27 +94,18 @@ namespace OpenTK.Platform.Windows
// Raise the Create event
this.OnCreate(EventArgs.Empty);
// Raise the resize event:
//resizeEventArgs.Width = width;
//resizeEventArgs.Height = height;
//this.OnResize(resizeEventArgs);
return;
//case API.Constants.WM_KEYDOWN: // Legacy input events
//case API.Constants.WM_KEYUP:
// break;
case API.Constants.WM_CLOSE:
//this.Exit();
//return;
break;
this.Exit();
return;
case API.Constants.WM_DESTROY:
if (this.Handle != IntPtr.Zero)
{
Debug.Print("Window handle {0} destroyed.", this.Handle);
this.DestroyHandle();
exists = false;
}
API.PostQuitMessage(0);
return;
@ -174,7 +165,7 @@ namespace OpenTK.Platform.Windows
if (this.Handle != IntPtr.Zero && glContext != null)
{
Debug.WriteLine("Window creation was succesful.");
created = true;
exists = true;
}
else
{
@ -281,14 +272,14 @@ namespace OpenTK.Platform.Windows
#endregion
#region public bool Created
#region public bool Exists
/// <summary>
/// Returns true if a render window/context exists.
/// </summary>
public bool Created
public bool Exists
{
get { return created; }
get { return exists; }
}
#endregion

View file

@ -71,7 +71,7 @@ namespace OpenTK.Platform.Windows
KeyMap.Add(API.VirtualKeys.RCONTROL, Input.Key.ControlRight);
KeyMap.Add(API.VirtualKeys.RSHIFT, Input.Key.ShiftRight);
KeyMap.Add(API.VirtualKeys.RETURN, Input.Key.Enter);
KeyMap.Add(API.VirtualKeys.BACK, Input.Key.Backspace);
KeyMap.Add(API.VirtualKeys.BACK, Input.Key.BackSpace);
KeyMap.Add(API.VirtualKeys.OEM_1, Input.Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
KeyMap.Add(API.VirtualKeys.OEM_2, Input.Key.Slash); // Varies by keyboard, /? on Win2K/US

View file

@ -103,7 +103,7 @@ namespace OpenTK.Platform.X11
XSetWindowAttributes attributes = new XSetWindowAttributes();
attributes.colormap = glContext.colormap;
attributes.event_mask = (IntPtr)(EventMask.StructureNotifyMask);
attributes.event_mask = (IntPtr)(EventMask.StructureNotifyMask | EventMask.ExposureMask);
SetWindowValuemask mask = SetWindowValuemask.ColorMap | SetWindowValuemask.EventMask;
@ -163,13 +163,12 @@ namespace OpenTK.Platform.X11
public void Exit()
{
/*Event e = new Event();
X11Api.SendEvent(
display,
window,
false,
0,*/
//quit = true;
Debug.WriteLine("X11GLNative shutdown sequence initiated.");
quit = true;
Functions.XDestroyWindow(window.Display, window.Handle);
window = null;
glContext.Dispose();
glContext = null;
}
#endregion
@ -181,7 +180,6 @@ namespace OpenTK.Platform.X11
// Process all pending events
while (true)
{
//pending = Functions.XPending(info.Display);
pending = Functions.XPending(window.Display);
if (pending == 0)
@ -201,15 +199,14 @@ namespace OpenTK.Platform.X11
break;
case XEventName.CreateNotify:
// A child was created - nothing to do
// A child was exists - nothing to do
break;
case XEventName.DestroyNotify:
glContext.Dispose();
Functions.XDestroyWindow(window.Display, window.Handle);
window = null;
glContext = null;
quit = true;
//glContext.Dispose();
//window = null;
//glContext = null;
//quit = true;
Debug.WriteLine("Window destroyed, shutting down.");
break;
@ -257,12 +254,12 @@ namespace OpenTK.Platform.X11
#endregion
#region public bool Created
#region public bool Exists
/// <summary>
/// Returns true if a render window/context exists.
/// </summary>
public bool Created
public bool Exists
{
get { return created; }
}

View file

@ -126,39 +126,8 @@ namespace OpenTK.Platform.X11
{
while (API.CheckMaskEvent(window.Display, EventMask.KeyReleaseMask | EventMask.KeyPressMask, ref e))
{
Debug.Print("Input window received {0} event... ", e.type.ToString());
keyboardDriver.ProcessKeyboardEvent(e.KeyEvent);
}
/*
try
{
while (API.CheckIfEvent(window.Display, ref e, check, IntPtr.Zero))
{
Debug.Print("Input window received {0} event... ", e.type.ToString());
keyboardDriver.ProcessKeyboardEvent(e.KeyEvent);
}
}
catch (Exception e)
{
Debug.Print("DANGER: Possible callback exception: {0}", e.ToString());
}
*/
}
API.CheckEventPredicate check = KeyEventPredicate;
private static bool KeyEventPredicate(IntPtr display, ref XEvent @event, IntPtr arg)
{
bool ret = false;
try
{
ret = (@event.type == XEventName.KeyRelease || @event.type == XEventName.KeyPress);
}
catch (Exception e)
{
Debug.Print("DANGER: Exception caught during unmanaged callback: {0}", e.ToString());
}
return ret;
}
#endregion

View file

@ -41,6 +41,11 @@ namespace OpenTK.Platform.X11
{
if (!keymapExists)
{
keymap.Add(XKey.Escape, Key.Escape);
keymap.Add(XKey.Return, Key.Enter);
keymap.Add(XKey.space, Key.Space);
keymap.Add(XKey.BackSpace, Key.BackSpace);
keymap.Add(XKey.Shift_L, Key.ShiftLeft);
keymap.Add(XKey.Shift_R, Key.ShiftRight);
keymap.Add(XKey.Alt_L, Key.AltLeft);
@ -57,22 +62,21 @@ namespace OpenTK.Platform.X11
keymap.Add(XKey.minus, Key.Minus);
keymap.Add(XKey.plus, Key.Plus);
keymap.Add(XKey.equal, Key.Plus);
//keymap.Add
keymap.Add(XKey.Caps_Lock, Key.CapsLock);
keymap.Add(XKey.Num_Lock, Key.NumLock);
for (int i = (int)XKey.F1; i < (int)XKey.F35; i++)
for (int i = (int)XKey.F1; i <= (int)XKey.F35; i++)
{
keymap.Add((XKey)i, (Key)((int)Key.F1 + (i - (int)XKey.F1)));
}
for (int i = (int)XKey.a; i < (int)XKey.z; i++)
for (int i = (int)XKey.a; i <= (int)XKey.z; i++)
{
keymap.Add((XKey)i, (Key)((int)Key.A + (i - (int)XKey.a)));
}
for (int i = (int)XKey.A; i < (int)XKey.Z; i++)
for (int i = (int)XKey.A; i <= (int)XKey.Z; i++)
{
keymap.Add((XKey)i, (Key)((int)Key.A + (i - (int)XKey.A)));
}
@ -94,6 +98,8 @@ namespace OpenTK.Platform.X11
keymap.Add(XKey.Print, Key.PrintScreen);
keymap.Add(XKey.Sys_Req, Key.PrintScreen);
keymap.Add(XKey.backslash, Key.BackSlash);
keymap.Add(XKey.bar, Key.BackSlash);
keymap.Add(XKey.braceleft, Key.BracketLeft);
keymap.Add(XKey.bracketleft, Key.BracketLeft);
keymap.Add(XKey.braceright, Key.BracketRight);
@ -102,6 +108,8 @@ namespace OpenTK.Platform.X11
keymap.Add(XKey.semicolon, Key.Semicolon);
keymap.Add(XKey.quoteright, Key.Quote);
keymap.Add(XKey.quotedbl, Key.Quote);
keymap.Add(XKey.quoteleft, Key.Tilde);
keymap.Add(XKey.asciitilde, Key.Tilde);
keymap.Add(XKey.comma, Key.Comma);
keymap.Add(XKey.less, Key.Comma);
@ -110,6 +118,35 @@ namespace OpenTK.Platform.X11
keymap.Add(XKey.slash, Key.Slash);
keymap.Add(XKey.question, Key.Slash);
keymap.Add(XKey.Left, Key.Left);
keymap.Add(XKey.Down, Key.Down);
keymap.Add(XKey.Right, Key.Right);
keymap.Add(XKey.Up, Key.Up);
keymap.Add(XKey.Delete, Key.Delete);
keymap.Add(XKey.Home, Key.Home);
keymap.Add(XKey.End, Key.End);
//keymap.Add(XKey.Prior, Key.PageUp); // XKey.Prior == XKey.Page_Up
keymap.Add(XKey.Page_Up, Key.PageUp);
keymap.Add(XKey.Page_Down, Key.PageDown);
//keymap.Add(XKey.Next, Key.PageDown); // XKey.Next == XKey.Page_Down
keymap.Add(XKey.KP_Add, Key.KeypadAdd);
keymap.Add(XKey.KP_Subtract, Key.KeypadSubtract);
keymap.Add(XKey.KP_Multiply, Key.KeypadMultiply);
keymap.Add(XKey.KP_Divide, Key.KeypadDivide);
keymap.Add(XKey.KP_Decimal, Key.KeypadDecimal);
keymap.Add(XKey.KP_Insert, Key.Keypad0);
keymap.Add(XKey.KP_End, Key.Keypad1);
keymap.Add(XKey.KP_Down, Key.Keypad2);
keymap.Add(XKey.KP_Page_Down, Key.Keypad3);
keymap.Add(XKey.KP_Left, Key.Keypad4);
keymap.Add(XKey.KP_Right, Key.Keypad6);
keymap.Add(XKey.KP_Home, Key.Keypad7);
keymap.Add(XKey.KP_Up, Key.Keypad8);
keymap.Add(XKey.KP_Page_Up, Key.Keypad9);
keymap.Add(XKey.KP_Delete, Key.KeypadDecimal);
keymap.Add(XKey.KP_Enter, Key.Enter);
keymapExists = true;
}
@ -139,6 +176,7 @@ namespace OpenTK.Platform.X11
kb.Description = "Default X11 keyboard";
kb.NumberOfKeys = lastKeyCode - firstKeyCode + 1;
keyboards.Add(kb);
Debug.Print("Keyboard added: {0}", kb.ToString());
}
#region internal bool ProcessKeyboardEvent(X11.KeyEvent e)
@ -171,55 +209,11 @@ namespace OpenTK.Platform.X11
else
{
Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
return false;
}
return true;
}
return false;
/*API.e.keycode
switch (rin.Header.Type)
{
case API.RawInputDeviceType.KEYBOARD:
bool pressed =
rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN ||
rin.Data.Keyboard.Message == API.Constants.WM_SYSKEYDOWN;
// Generic control, shift, alt keys may be sent instead of left/right.
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey)
{
case API.VirtualKeys.SHIFT:
keyboards[0][Input.Key.ShiftLeft] = keyboards[0][Input.Key.ShiftRight] = pressed;
return false;
case API.VirtualKeys.CONTROL:
keyboards[0][Input.Key.ControlLeft] = keyboards[0][Input.Key.ControlRight] = pressed;
return false;
case API.VirtualKeys.MENU:
keyboards[0][Input.Key.AltLeft] = keyboards[0][Input.Key.AltRight] = pressed;
return false;
default:
if (!WinRawKeyboard.KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
{
Debug.Print("Virtual key {0} not mapped.", rin.Data.Keyboard.VKey);
OpenTK.OpenGL.GL.ClearColor(1.0f, 0.3f, 0.3f, 0.0f);
}
else
{
keyboards[0][WinRawKeyboard.KeyMap[rin.Data.Keyboard.VKey]] = pressed;
OpenTK.OpenGL.GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
break;
}
break;
default:
throw new ApplicationException("Windows raw keyboard driver received invalid data.");
}
return false;*/
}
#endregion