diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs
index 1fc3af41..2fa96467 100644
--- a/Source/OpenTK/GameWindow.cs
+++ b/Source/OpenTK/GameWindow.cs
@@ -240,6 +240,8 @@ namespace OpenTK
glWindow.Closing += delegate(object sender, CancelEventArgs e) { OnClosingInternal(e); };
glWindow.Closed += delegate(object sender, EventArgs e) { OnClosedInternal(e); };
//glWindow.WindowInfoChanged += delegate(object sender, EventArgs e) { OnWindowInfoChangedInternal(e); };
+ glWindow.WindowBorderChanged += delegate(object sender, EventArgs e) { OnWindowBorderChangedInternal(e); };
+ glWindow.WindowStateChanged += delegate(object sender, EventArgs e) { OnWindowStateChangedInternal(e); };
}
catch (Exception e)
{
@@ -379,6 +381,28 @@ namespace OpenTK
#endregion
+ #region OnWindowBorderChangedInternal
+
+ void OnWindowBorderChangedInternal(EventArgs e)
+ {
+ OnWindowBorderChanged(e);
+
+ WindowBorderChanged(this, EventArgs.Empty);
+ }
+
+ #endregion
+
+ #region OnWindowStateChangedInternal
+
+ void OnWindowStateChangedInternal(EventArgs e)
+ {
+ OnWindowStateChanged(e);
+
+ WindowStateChanged(this, e);
+ }
+
+ #endregion
+
#region OnUpdateFrameInternal
private void OnUpdateFrameInternal(FrameEventArgs e)
@@ -456,6 +480,20 @@ namespace OpenTK
protected virtual void OnWindowInfoChanged(EventArgs e)
{ }
+ ///
+ /// Called when the WindowBorder for this GameWindow has changed.
+ ///
+ /// Not used.
+ protected virtual void OnWindowBorderChanged(EventArgs e)
+ { }
+
+ ///
+ /// Called when the WindowState for this GameWindow has changed.
+ ///
+ /// Not used.
+ protected virtual void OnWindowStateChanged(EventArgs e)
+ { }
+
#endregion
#region --- Public Members ---
@@ -1440,6 +1478,16 @@ namespace OpenTK
///
public event EventHandler FocusedChanged = delegate { };
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler WindowBorderChanged = delegate { };
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ public event EventHandler WindowStateChanged = delegate { };
+
///
/// Occurs whenever a character is typed.
///
diff --git a/Source/OpenTK/INativeWindow.cs b/Source/OpenTK/INativeWindow.cs
index 7513f6d0..dd7685d1 100644
--- a/Source/OpenTK/INativeWindow.cs
+++ b/Source/OpenTK/INativeWindow.cs
@@ -196,6 +196,16 @@ namespace OpenTK
///
event EventHandler FocusedChanged;
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ event EventHandler WindowBorderChanged;
+
+ ///
+ /// Occurs when the property of the window changes.
+ ///
+ event EventHandler WindowStateChanged;
+
///
/// Occurs whenever a character is typed.
///
diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
index 02d75379..5e881b6b 100644
--- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
+++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
@@ -678,103 +678,6 @@ namespace OpenTK.Platform.MacOS
#endregion
- #region INativeGLWindow Members
-
- public WindowState WindowState
- {
- get
- {
- if (windowState == WindowState.Fullscreen)
- return WindowState.Fullscreen;
-
- if (Carbon.API.IsWindowCollapsed(window.WindowRef))
- return WindowState.Minimized;
-
-
- if (Carbon.API.IsWindowInStandardState(window.WindowRef))
- {
- return WindowState.Maximized;
- }
-
- return WindowState.Normal;
- }
- set
- {
- if (value == WindowState)
- return;
-
- Debug.Print("Switching window state from {0} to {1}", WindowState, value);
-
- if (WindowState == WindowState.Fullscreen)
- {
- UnsetFullscreen();
- }
- if (WindowState == WindowState.Minimized)
- {
- API.CollapseWindow(window.WindowRef, false);
- }
- Point idealSize;
-
- switch (value)
- {
- case WindowState.Fullscreen:
- SetFullscreen();
-
- break;
-
- case WindowState.Maximized:
- // hack because mac os has no concept of maximized. Instead windows are "zoomed"
- // meaning they are maximized up to their reported ideal size. So we report a
- // large ideal size.
- idealSize = new Point(9000, 9000);
- API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
- break;
-
- case WindowState.Normal:
- if (WindowState == WindowState.Maximized)
- {
- idealSize = new Point();
- API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomIn, ref idealSize);
- }
- break;
-
- case WindowState.Minimized:
- API.CollapseWindow(window.WindowRef, true);
-
- break;
- }
-
- windowState = value;
-
- OnResize();
- }
- }
-
- public WindowBorder WindowBorder
- {
- get
- {
- return windowBorder;
- }
- set
- {
- windowBorder = value;
-
- if (windowBorder == WindowBorder.Resizable)
- {
- API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.Resizable | WindowAttributes.FullZoom,
- WindowAttributes.NoAttributes);
- }
- else if (windowBorder == WindowBorder.Fixed)
- {
- API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.NoAttributes,
- WindowAttributes.Resizable | WindowAttributes.FullZoom);
- }
- }
- }
-
- #endregion
-
#region INativeWindow Members
public string Title
@@ -802,18 +705,6 @@ namespace OpenTK.Platform.MacOS
}
}
- public System.Drawing.Icon Icon
- {
- get
- {
- throw new NotImplementedException();
- }
- set
- {
- throw new NotImplementedException();
- }
- }
-
public bool Focused
{
get { throw new NotImplementedException(); }
@@ -921,6 +812,108 @@ namespace OpenTK.Platform.MacOS
throw new NotImplementedException();
}
+ public WindowState WindowState
+ {
+ get
+ {
+ if (windowState == WindowState.Fullscreen)
+ return WindowState.Fullscreen;
+
+ if (Carbon.API.IsWindowCollapsed(window.WindowRef))
+ return WindowState.Minimized;
+
+
+ if (Carbon.API.IsWindowInStandardState(window.WindowRef))
+ {
+ return WindowState.Maximized;
+ }
+
+ return WindowState.Normal;
+ }
+ set
+ {
+ if (value == WindowState)
+ return;
+
+ Debug.Print("Switching window state from {0} to {1}", WindowState, value);
+
+ if (WindowState == WindowState.Fullscreen)
+ {
+ UnsetFullscreen();
+ }
+ if (WindowState == WindowState.Minimized)
+ {
+ API.CollapseWindow(window.WindowRef, false);
+ }
+ Point idealSize;
+
+ switch (value)
+ {
+ case WindowState.Fullscreen:
+ SetFullscreen();
+
+ break;
+
+ case WindowState.Maximized:
+ // hack because mac os has no concept of maximized. Instead windows are "zoomed"
+ // meaning they are maximized up to their reported ideal size. So we report a
+ // large ideal size.
+ idealSize = new Point(9000, 9000);
+ API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
+ break;
+
+ case WindowState.Normal:
+ if (WindowState == WindowState.Maximized)
+ {
+ idealSize = new Point();
+ API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomIn, ref idealSize);
+ }
+ break;
+
+ case WindowState.Minimized:
+ API.CollapseWindow(window.WindowRef, true);
+
+ break;
+ }
+
+ windowState = value;
+
+ if (WindowStateChanged != null)
+ WindowStateChanged(this, EventArgs.Empty);
+
+ OnResize();
+ }
+ }
+
+ public WindowBorder WindowBorder
+ {
+ get
+ {
+ return windowBorder;
+ }
+ set
+ {
+ if (windowBorder != value)
+ {
+ windowBorder = value;
+
+ if (windowBorder == WindowBorder.Resizable)
+ {
+ API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.Resizable | WindowAttributes.FullZoom,
+ WindowAttributes.NoAttributes);
+ }
+ else if (windowBorder == WindowBorder.Fixed)
+ {
+ API.ChangeWindowAttributes(window.WindowRef, WindowAttributes.NoAttributes,
+ WindowAttributes.Resizable | WindowAttributes.FullZoom);
+ }
+
+ if (WindowBorderChanged != null)
+ WindowBorderChanged(this, EventArgs.Empty);
+ }
+ }
+ }
+
public event EventHandler Idle;
public event EventHandler Load;
@@ -949,6 +942,10 @@ namespace OpenTK.Platform.MacOS
public event EventHandler FocusedChanged;
+ public event EventHandler WindowBorderChanged;
+
+ public event EventHandler WindowStateChanged;
+
public event EventHandler KeyPress;
#endregion
diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs
index 6a6fc8e8..349b01bb 100644
--- a/Source/OpenTK/Platform/Windows/WinGLNative.cs
+++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs
@@ -797,6 +797,9 @@ namespace OpenTK.Platform.Windows
break;
}
+ if (WindowStateChanged != null)
+ WindowStateChanged(this, EventArgs.Empty);
+
if (command != 0)
Functions.ShowWindow(window.WindowHandle, command);
}
@@ -849,6 +852,9 @@ namespace OpenTK.Platform.Windows
SetWindowPosFlags.FRAMECHANGED);
Visible = true;
+
+ if (WindowBorderChanged != null)
+ WindowBorderChanged(this, EventArgs.Empty);
}
}
@@ -907,6 +913,10 @@ namespace OpenTK.Platform.Windows
public event EventHandler FocusedChanged;
+ public event EventHandler WindowBorderChanged;
+
+ public event EventHandler WindowStateChanged;
+
public event EventHandler KeyPress;
#endregion
diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs
index c69f6243..f0e506c3 100644
--- a/Source/OpenTK/Platform/X11/X11GLNative.cs
+++ b/Source/OpenTK/Platform/X11/X11GLNative.cs
@@ -516,7 +516,7 @@ namespace OpenTK.Platform.X11
#region INativeWindow Members
- #region ProcessEvents
+ #region ProcessEvents
public void ProcessEvents()
{
@@ -839,6 +839,181 @@ namespace OpenTK.Platform.X11
#endregion
+ #region WindowState
+
+ public OpenTK.WindowState WindowState
+ {
+ get
+ {
+ IntPtr actual_atom;
+ int actual_format;
+ IntPtr nitems;
+ IntPtr bytes_after;
+ IntPtr prop = IntPtr.Zero;
+ IntPtr atom;
+ //XWindowAttributes attributes;
+ bool fullscreen = false;
+ int maximized = 0;
+ bool minimized = false;
+
+ Functions.XGetWindowProperty(window.Display, window.WindowHandle,
+ _atom_net_wm_state, IntPtr.Zero, new IntPtr(256), false,
+ IntPtr.Zero, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+
+ if ((long)nitems > 0 && prop != IntPtr.Zero)
+ {
+ for (int i = 0; i < (long)nitems; i++)
+ {
+ atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
+
+ if (atom == _atom_net_wm_state_maximized_horizontal ||
+ atom == _atom_net_wm_state_maximized_vertical)
+ maximized++;
+ else if (atom == _atom_net_wm_state_minimized)
+ minimized = true;
+ else if (atom == _atom_net_wm_state_fullscreen)
+ fullscreen = true;
+ }
+ Functions.XFree(prop);
+ }
+
+ if (minimized)
+ return OpenTK.WindowState.Minimized;
+ else if (maximized == 2)
+ return OpenTK.WindowState.Maximized;
+ else if (fullscreen)
+ return OpenTK.WindowState.Fullscreen;
+ /*
+ attributes = new XWindowAttributes();
+ Functions.XGetWindowAttributes(window.Display, window.WindowHandle, ref attributes);
+ if (attributes.map_state == MapState.IsUnmapped)
+ return (OpenTK.WindowState)(-1);
+ */
+ return OpenTK.WindowState.Normal;
+ }
+ set
+ {
+ OpenTK.WindowState current_state = this.WindowState;
+
+ if (current_state == value)
+ return;
+
+ Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
+ current_state.ToString(), value.ToString());
+
+ if (current_state == OpenTK.WindowState.Minimized)
+ Functions.XMapWindow(window.Display, window.WindowHandle);
+ 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;
+ }
+
+ switch (value)
+ {
+ case OpenTK.WindowState.Normal:
+ Functions.XRaiseWindow(window.Display, window.WindowHandle);
+
+ 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.WindowHandle);
+
+ break;
+
+ case OpenTK.WindowState.Minimized:
+ // Todo: multiscreen support
+ Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
+
+ 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.WindowHandle);
+
+ break;
+ }
+
+ if (temporary_resizable)
+ WindowBorder = previous_state;
+
+ if (WindowStateChanged != null)
+ WindowStateChanged(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+ #region WindowBorder
+
+ public OpenTK.WindowBorder WindowBorder
+ {
+ get
+ {
+ if (IsWindowBorderHidden)
+ return WindowBorder.Hidden;
+
+ if (IsWindowBorderResizable)
+ return WindowBorder.Resizable;
+ else
+ return WindowBorder.Fixed;
+ }
+ set
+ {
+ if (WindowBorder == value)
+ return;
+
+ 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.");
+ DisableWindowDecorations();
+
+ break;
+ }
+
+ if (WindowBorderChanged != null)
+ WindowBorderChanged(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
#region Events
public event EventHandler Load;
@@ -863,6 +1038,10 @@ namespace OpenTK.Platform.X11
public event EventHandler FocusedChanged;
+ public event EventHandler WindowBorderChanged;
+
+ public event EventHandler WindowStateChanged;
+
public event EventHandler KeyPress;
#endregion
@@ -1128,175 +1307,6 @@ namespace OpenTK.Platform.X11
#endregion
- #region publicOpenTK.WindowState WindowState
-
- public OpenTK.WindowState WindowState
- {
- get
- {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- IntPtr atom;
- //XWindowAttributes attributes;
- bool fullscreen = false;
- int maximized = 0;
- bool minimized = false;
-
- Functions.XGetWindowProperty(window.Display, window.WindowHandle,
- _atom_net_wm_state, IntPtr.Zero, new IntPtr (256), false,
- IntPtr.Zero, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-
- if ((long)nitems > 0 && prop != IntPtr.Zero)
- {
- for (int i = 0; i < (long)nitems; i++)
- {
- atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
-
- if (atom == _atom_net_wm_state_maximized_horizontal ||
- atom == _atom_net_wm_state_maximized_vertical)
- maximized++;
- else if (atom == _atom_net_wm_state_minimized)
- minimized = true;
- else if (atom == _atom_net_wm_state_fullscreen)
- fullscreen = true;
- }
- Functions.XFree(prop);
- }
-
- if (minimized)
- return OpenTK.WindowState.Minimized;
- else if (maximized == 2)
- return OpenTK.WindowState.Maximized;
- else if (fullscreen)
- return OpenTK.WindowState.Fullscreen;
-/*
- attributes = new XWindowAttributes();
- Functions.XGetWindowAttributes(window.Display, window.WindowHandle, ref attributes);
- if (attributes.map_state == MapState.IsUnmapped)
- return (OpenTK.WindowState)(-1);
-*/
- return OpenTK.WindowState.Normal;
- }
- set
- {
- OpenTK.WindowState current_state = this.WindowState;
-
- if (current_state == value)
- return;
-
- Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
- current_state.ToString(), value.ToString());
-
- if (current_state == OpenTK.WindowState.Minimized)
- Functions.XMapWindow(window.Display, window.WindowHandle);
- 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;
- }
-
- switch (value)
- {
- case OpenTK.WindowState.Normal:
- Functions.XRaiseWindow(window.Display, window.WindowHandle);
-
- 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.WindowHandle);
-
- break;
-
- case OpenTK.WindowState.Minimized:
- // Todo: multiscreen support
- Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
-
- 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.WindowHandle);
-
- break;
- }
-
- if (temporary_resizable)
- WindowBorder = previous_state;
- }
- }
-
- #endregion
-
- #region public OpenTK.WindowBorder WindowBorder
-
- public OpenTK.WindowBorder WindowBorder
- {
- get
- {
- if (IsWindowBorderHidden)
- return WindowBorder.Hidden;
-
- if (IsWindowBorderResizable)
- return WindowBorder.Resizable;
- else
- return WindowBorder.Fixed;
- }
- set
- {
- if (WindowBorder == value)
- return;
-
- 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.");
- DisableWindowDecorations();
-
- break;
- }
- }
- }
-
- #endregion
-
#endregion
#region IDisposable Members