Implemented INativeWindow.WindowBorderChanged and INativeWindow.WindowStateChanged events.

This commit is contained in:
the_fiddler 2009-08-17 09:34:15 +00:00
parent 878dd4394c
commit 5e80a061b8
5 changed files with 354 additions and 279 deletions

View file

@ -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)
{ }
/// <summary>
/// Called when the WindowBorder for this GameWindow has changed.
/// </summary>
/// <param name="e">Not used.</param>
protected virtual void OnWindowBorderChanged(EventArgs e)
{ }
/// <summary>
/// Called when the WindowState for this GameWindow has changed.
/// </summary>
/// <param name="e">Not used.</param>
protected virtual void OnWindowStateChanged(EventArgs e)
{ }
#endregion
#region --- Public Members ---
@ -1440,6 +1478,16 @@ namespace OpenTK
/// </summary>
public event EventHandler<EventArgs> FocusedChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="WindowBorder"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
/// <summary>
/// Occurs when the <see cref="WindowState"/> property of the window changes.
/// </summary>
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
/// <summary>
/// Occurs whenever a character is typed.
/// </summary>

View file

@ -196,6 +196,16 @@ namespace OpenTK
/// </summary>
event EventHandler<EventArgs> FocusedChanged;
/// <summary>
/// Occurs when the <see cref="WindowBorder"/> property of the window changes.
/// </summary>
event EventHandler<EventArgs> WindowBorderChanged;
/// <summary>
/// Occurs when the <see cref="WindowState"/> property of the window changes.
/// </summary>
event EventHandler<EventArgs> WindowStateChanged;
/// <summary>
/// Occurs whenever a character is typed.
/// </summary>

View file

@ -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<EventArgs> Idle;
public event EventHandler<EventArgs> Load;
@ -949,6 +942,10 @@ namespace OpenTK.Platform.MacOS
public event EventHandler<EventArgs> FocusedChanged;
public event EventHandler<EventArgs> WindowBorderChanged;
public event EventHandler<EventArgs> WindowStateChanged;
public event EventHandler<KeyPressEventArgs> KeyPress;
#endregion

View file

@ -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<EventArgs> FocusedChanged;
public event EventHandler<EventArgs> WindowBorderChanged;
public event EventHandler<EventArgs> WindowStateChanged;
public event EventHandler<KeyPressEventArgs> KeyPress;
#endregion

View file

@ -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<EventArgs> Load;
@ -863,6 +1038,10 @@ namespace OpenTK.Platform.X11
public event EventHandler<EventArgs> FocusedChanged;
public event EventHandler<EventArgs> WindowBorderChanged;
public event EventHandler<EventArgs> WindowStateChanged;
public event EventHandler<KeyPressEventArgs> 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