Merge pull request #38 from opentk/issue34

Fix for issue #33 and issue #34
This commit is contained in:
thefiddler 2014-01-08 13:36:32 -08:00
commit 811126c47b
2 changed files with 393 additions and 253 deletions

View file

@ -151,7 +151,12 @@ namespace OpenTK.Platform.Windows
internal static extern BOOL AdjustWindowRect([In, Out] ref Win32Rectangle lpRect, WindowStyle dwStyle, BOOL bMenu); internal static extern BOOL AdjustWindowRect([In, Out] ref Win32Rectangle lpRect, WindowStyle dwStyle, BOOL bMenu);
[DllImport("user32.dll", EntryPoint = "AdjustWindowRectEx", CallingConvention = CallingConvention.StdCall, SetLastError = true), SuppressUnmanagedCodeSecurity] [DllImport("user32.dll", EntryPoint = "AdjustWindowRectEx", CallingConvention = CallingConvention.StdCall, SetLastError = true), SuppressUnmanagedCodeSecurity]
internal static extern bool AdjustWindowRectEx(ref Win32Rectangle lpRect, WindowStyle dwStyle, bool bMenu, ExtendedWindowStyle dwExStyle); [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustWindowRectEx(
ref Win32Rectangle lpRect,
WindowStyle dwStyle,
[MarshalAs(UnmanagedType.Bool)] bool bMenu,
ExtendedWindowStyle dwExStyle);
#endregion #endregion
@ -241,9 +246,7 @@ namespace OpenTK.Platform.Windows
#region CallWindowProc #region CallWindowProc
#if RELEASE
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
#endif
[DllImport("user32.dll", SetLastError = true)] [DllImport("user32.dll", SetLastError = true)]
internal static extern LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, WindowMessage Msg, internal static extern LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, WindowMessage Msg,
WPARAM wParam, LPARAM lParam); WPARAM wParam, LPARAM lParam);
@ -264,9 +267,9 @@ namespace OpenTK.Platform.Windows
SetLastError(0); SetLastError(0);
if (IntPtr.Size == 4) if (IntPtr.Size == 4)
retval = new IntPtr(SetWindowLong(handle, item, newValue.ToInt32())); retval = new IntPtr(SetWindowLongInternal(handle, item, newValue.ToInt32()));
else else
retval = SetWindowLongPtr(handle, item, newValue); retval = SetWindowLongPtrInternal(handle, item, newValue);
if (retval == IntPtr.Zero) if (retval == IntPtr.Zero)
{ {
@ -283,30 +286,22 @@ namespace OpenTK.Platform.Windows
return SetWindowLong(handle, GetWindowLongOffsets.WNDPROC, Marshal.GetFunctionPointerForDelegate(newValue)); return SetWindowLong(handle, GetWindowLongOffsets.WNDPROC, Marshal.GetFunctionPointerForDelegate(newValue));
} }
#if RELASE
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
#endif [DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")]
[DllImport("user32.dll", SetLastError = true)] static extern LONG SetWindowLongInternal(HWND hWnd, GetWindowLongOffsets nIndex, LONG dwNewLong);
static extern LONG SetWindowLong(HWND hWnd, GetWindowLongOffsets nIndex, LONG dwNewLong);
#if RELASE
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
#endif [DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongPtr")]
[DllImport("user32.dll", SetLastError = true)] static extern LONG_PTR SetWindowLongPtrInternal(HWND hWnd, GetWindowLongOffsets nIndex, LONG_PTR dwNewLong);
static extern LONG_PTR SetWindowLongPtr(HWND hWnd, GetWindowLongOffsets nIndex, LONG_PTR dwNewLong);
#if RELASE
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
#endif [DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")]
[DllImport("user32.dll", SetLastError = true)] static extern LONG SetWindowLongInternal(HWND hWnd, GetWindowLongOffsets nIndex,
static extern LONG SetWindowLong(HWND hWnd, GetWindowLongOffsets nIndex,
[MarshalAs(UnmanagedType.FunctionPtr)]WindowProcedure dwNewLong); [MarshalAs(UnmanagedType.FunctionPtr)]WindowProcedure dwNewLong);
#if RELASE
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
#endif [DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongPtr")]
[DllImport("user32.dll", SetLastError = true)] static extern LONG_PTR SetWindowLongPtrInternal(HWND hWnd, GetWindowLongOffsets nIndex,
static extern LONG_PTR SetWindowLongPtr(HWND hWnd, GetWindowLongOffsets nIndex,
[MarshalAs(UnmanagedType.FunctionPtr)]WindowProcedure dwNewLong); [MarshalAs(UnmanagedType.FunctionPtr)]WindowProcedure dwNewLong);
#endregion #endregion
@ -407,9 +402,7 @@ namespace OpenTK.Platform.Windows
#region DispatchMessage #region DispatchMessage
#if RELEASE [SuppressUnmanagedCodeSecurity]
[System.Security.SuppressUnmanagedCodeSecurity]
#endif
[DllImport("User32.dll"), CLSCompliant(false)] [DllImport("User32.dll"), CLSCompliant(false)]
internal static extern LRESULT DispatchMessage(ref MSG msg); internal static extern LRESULT DispatchMessage(ref MSG msg);
@ -417,9 +410,7 @@ namespace OpenTK.Platform.Windows
#region TranslateMessage #region TranslateMessage
#if RELEASE [SuppressUnmanagedCodeSecurity]
[System.Security.SuppressUnmanagedCodeSecurity]
#endif
[DllImport("User32.dll"), CLSCompliant(false)] [DllImport("User32.dll"), CLSCompliant(false)]
internal static extern BOOL TranslateMessage(ref MSG lpMsg); internal static extern BOOL TranslateMessage(ref MSG lpMsg);
@ -3752,7 +3743,7 @@ namespace OpenTK.Platform.Windows
#region WindowMessage #region WindowMessage
internal enum WindowMessage : uint internal enum WindowMessage : int
{ {
NULL = 0x0000, NULL = 0x0000,
CREATE = 0x0001, CREATE = 0x0001,

View file

@ -240,15 +240,10 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region WindowProcedure #region Message Handlers
IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) void HandleActivate(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{ {
switch (message)
{
#region Size / Move / Style events
case WindowMessage.ACTIVATE:
// See http://msdn.microsoft.com/en-us/library/ms646274(VS.85).aspx (WM_ACTIVATE notification): // See http://msdn.microsoft.com/en-us/library/ms646274(VS.85).aspx (WM_ACTIVATE notification):
// wParam: The low-order word specifies whether the window is being activated or deactivated. // wParam: The low-order word specifies whether the window is being activated or deactivated.
bool new_focused_state = Focused; bool new_focused_state = Focused;
@ -259,10 +254,10 @@ namespace OpenTK.Platform.Windows
if (new_focused_state != Focused) if (new_focused_state != Focused)
FocusedChanged(this, EventArgs.Empty); FocusedChanged(this, EventArgs.Empty);
break; }
case WindowMessage.ENTERMENULOOP: void HandleEnterModalLoop(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
case WindowMessage.ENTERSIZEMOVE: {
// Entering the modal size/move loop: we don't want rendering to // Entering the modal size/move loop: we don't want rendering to
// stop during this time, so we register a timer callback to continue // stop during this time, so we register a timer callback to continue
// processing from time to time. // processing from time to time.
@ -271,10 +266,10 @@ namespace OpenTK.Platform.Windows
if (!CursorVisible) if (!CursorVisible)
UngrabCursor(); UngrabCursor();
break; }
case WindowMessage.EXITMENULOOP: void HandleExitModalLoop(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
case WindowMessage.EXITSIZEMOVE: {
// Exiting from Modal size/move loop: the timer callback is no longer // Exiting from Modal size/move loop: the timer callback is no longer
// necessary. // necessary.
is_in_modal_loop = false; is_in_modal_loop = false;
@ -283,12 +278,10 @@ namespace OpenTK.Platform.Windows
// Ensure cursor remains grabbed // Ensure cursor remains grabbed
if (!CursorVisible) if (!CursorVisible)
GrabCursor(); GrabCursor();
break; }
case WindowMessage.ERASEBKGND: void HandleWindowPositionChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
return new IntPtr(1); {
case WindowMessage.WINDOWPOSCHANGED:
unsafe unsafe
{ {
WindowPosition* pos = (WindowPosition*)lParam; WindowPosition* pos = (WindowPosition*)lParam;
@ -329,38 +322,56 @@ namespace OpenTK.Platform.Windows
} }
} }
} }
break; }
void HandleStyleChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
WindowBorder old_border = windowBorder;
WindowBorder new_border = old_border;
case WindowMessage.STYLECHANGED:
unsafe unsafe
{ {
if (wParam.ToInt64() == (long)GWL.STYLE) GWL get_window_style = (GWL)unchecked(wParam.ToInt32());
if ((get_window_style & (GWL.STYLE | GWL.EXSTYLE)) != 0)
{ {
WindowStyle style = ((StyleStruct*)lParam)->New; WindowStyle style = ((StyleStruct*)lParam)->New;
if ((style & WindowStyle.Popup) != 0) if ((style & WindowStyle.Popup) != 0)
windowBorder = WindowBorder.Hidden; new_border = WindowBorder.Hidden;
else if ((style & WindowStyle.ThickFrame) != 0) else if ((style & WindowStyle.ThickFrame) != 0)
windowBorder = WindowBorder.Resizable; new_border = WindowBorder.Resizable;
else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0)
windowBorder = WindowBorder.Fixed; new_border = WindowBorder.Fixed;
} }
} }
if (new_border != windowBorder)
{
// Ensure cursor remains grabbed // Ensure cursor remains grabbed
if (!CursorVisible) if (!CursorVisible)
GrabCursor(); GrabCursor();
break; windowBorder = new_border;
WindowBorderChanged(this, EventArgs.Empty);
}
}
case WindowMessage.SIZE: void HandleSize(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
SizeMessage state = (SizeMessage)wParam.ToInt64(); SizeMessage state = (SizeMessage)wParam.ToInt64();
WindowState new_state = windowState; WindowState new_state = windowState;
switch (state) switch (state)
{ {
case SizeMessage.RESTORED: new_state = borderless_maximized_window_state ? case SizeMessage.RESTORED:
WindowState.Maximized : WindowState.Normal; break; new_state = borderless_maximized_window_state ?
case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break; WindowState.Maximized : WindowState.Normal;
case SizeMessage.MAXIMIZED: new_state = WindowBorder == WindowBorder.Hidden ? break;
case SizeMessage.MINIMIZED:
new_state = WindowState.Minimized;
break;
case SizeMessage.MAXIMIZED:
new_state = WindowBorder == WindowBorder.Hidden ?
WindowState.Fullscreen : WindowState.Maximized; WindowState.Fullscreen : WindowState.Maximized;
break; break;
} }
@ -374,23 +385,20 @@ namespace OpenTK.Platform.Windows
if (!CursorVisible) if (!CursorVisible)
GrabCursor(); GrabCursor();
} }
}
break; void HandleChar(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
#endregion
#region Input events
case WindowMessage.CHAR:
if (IntPtr.Size == 4) if (IntPtr.Size == 4)
key_press.KeyChar = (char)wParam.ToInt32(); key_press.KeyChar = (char)wParam.ToInt32();
else else
key_press.KeyChar = (char)wParam.ToInt64(); key_press.KeyChar = (char)wParam.ToInt64();
KeyPress(this, key_press); KeyPress(this, key_press);
break; }
case WindowMessage.MOUSEMOVE: void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Point point = new Point( Point point = new Point(
(short)((uint)lParam.ToInt32() & 0x0000FFFF), (short)((uint)lParam.ToInt32() & 0x0000FFFF),
(short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16)); (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16));
@ -405,68 +413,75 @@ namespace OpenTK.Platform.Windows
MouseEnter(this, EventArgs.Empty); MouseEnter(this, EventArgs.Empty);
} }
break; }
case WindowMessage.MOUSELEAVE: void HandleMouseLeave(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
mouse_outside_window = true; mouse_outside_window = true;
// Mouse tracking is disabled automatically by the OS // Mouse tracking is disabled automatically by the OS
MouseLeave(this, EventArgs.Empty); MouseLeave(this, EventArgs.Empty);
break; }
case WindowMessage.MOUSEWHEEL: void HandleMouseWheel(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
// This is due to inconsistent behavior of the WParam value on 64bit arch, whese // This is due to inconsistent behavior of the WParam value on 64bit arch, whese
// wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000 // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f; mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f;
break; }
case WindowMessage.LBUTTONDOWN: void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle); Functions.SetCapture(window.Handle);
mouse[MouseButton.Left] = true; mouse[MouseButton.Left] = true;
break; }
case WindowMessage.MBUTTONDOWN: void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle); Functions.SetCapture(window.Handle);
mouse[MouseButton.Middle] = true; mouse[MouseButton.Middle] = true;
break; }
case WindowMessage.RBUTTONDOWN: void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle); Functions.SetCapture(window.Handle);
mouse[MouseButton.Right] = true; mouse[MouseButton.Right] = true;
break; }
case WindowMessage.XBUTTONDOWN: void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.SetCapture(window.Handle); Functions.SetCapture(window.Handle);
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) !=
(int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
break; }
case WindowMessage.LBUTTONUP: void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture(); Functions.ReleaseCapture();
mouse[MouseButton.Left] = false; mouse[MouseButton.Left] = false;
break; }
case WindowMessage.MBUTTONUP: void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture(); Functions.ReleaseCapture();
mouse[MouseButton.Middle] = false; mouse[MouseButton.Middle] = false;
break; }
case WindowMessage.RBUTTONUP: void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture(); Functions.ReleaseCapture();
mouse[MouseButton.Right] = false; mouse[MouseButton.Right] = false;
break; }
case WindowMessage.XBUTTONUP: void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
Functions.ReleaseCapture(); Functions.ReleaseCapture();
mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) !=
(int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false;
break; }
// Keyboard events: void HandleKeyboard(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
case WindowMessage.KEYDOWN: {
case WindowMessage.KEYUP:
case WindowMessage.SYSKEYDOWN:
case WindowMessage.SYSKEYUP:
bool pressed = bool pressed =
message == WindowMessage.KEYDOWN || message == WindowMessage.KEYDOWN ||
message == WindowMessage.SYSKEYDOWN; message == WindowMessage.SYSKEYDOWN;
@ -498,23 +513,16 @@ namespace OpenTK.Platform.Windows
key_up.Key = key; key_up.Key = key;
KeyUp(this, key_up); KeyUp(this, key_up);
} }
}
} }
return IntPtr.Zero; void HandleKillFocus(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
case WindowMessage.SYSCHAR:
return IntPtr.Zero;
case WindowMessage.KILLFOCUS:
keyboard.ClearKeys(); keyboard.ClearKeys();
break; }
#endregion void HandleCreate(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
#region Creation / Destruction events
case WindowMessage.CREATE:
CreateStruct cs = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct)); CreateStruct cs = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct));
if (cs.hwndParent == IntPtr.Zero) if (cs.hwndParent == IntPtr.Zero)
{ {
@ -529,9 +537,10 @@ namespace OpenTK.Platform.Windows
invisible_since_creation = true; invisible_since_creation = true;
} }
break; }
case WindowMessage.CLOSE: void HandleClose(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs(); System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs();
Closing(this, e); Closing(this, e);
@ -539,20 +548,143 @@ namespace OpenTK.Platform.Windows
if (!e.Cancel) if (!e.Cancel)
{ {
DestroyWindow(); DestroyWindow();
break; }
} }
return IntPtr.Zero; void HandleDestroy(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
case WindowMessage.DESTROY:
exists = false; exists = false;
if (handle == window.Handle)
{
Functions.UnregisterClass(ClassName, Instance); Functions.UnregisterClass(ClassName, Instance);
}
window.Dispose(); window.Dispose();
child_window.Dispose(); child_window.Dispose();
Closed(this, EventArgs.Empty); Closed(this, EventArgs.Empty);
}
#endregion
#region WindowProcedure
IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
{
switch (message)
{
#region Size / Move / Style events
case WindowMessage.ACTIVATE:
HandleActivate(handle, message, wParam, lParam);
break;
case WindowMessage.ENTERMENULOOP:
case WindowMessage.ENTERSIZEMOVE:
HandleEnterModalLoop(handle, message, wParam, lParam);
break;
case WindowMessage.EXITMENULOOP:
case WindowMessage.EXITSIZEMOVE:
HandleExitModalLoop(handle, message, wParam, lParam);
break;
case WindowMessage.ERASEBKGND:
return new IntPtr(1);
case WindowMessage.WINDOWPOSCHANGED:
HandleWindowPositionChanged(handle, message, wParam, lParam);
break;
case WindowMessage.STYLECHANGED:
HandleStyleChanged(handle, message, wParam, lParam);
break;
case WindowMessage.SIZE:
HandleSize(handle, message, wParam, lParam);
break;
#endregion
#region Input events
case WindowMessage.CHAR:
HandleChar(handle, message, wParam, lParam);
break;
case WindowMessage.MOUSEMOVE:
HandleMouseMove(handle, message, wParam, lParam);
break;
case WindowMessage.MOUSELEAVE:
HandleMouseLeave(handle, message, wParam, lParam);
break;
case WindowMessage.MOUSEWHEEL:
HandleMouseWheel(handle, message, wParam, lParam);
break;
case WindowMessage.LBUTTONDOWN:
HandleLButtonDown(handle, message, wParam, lParam);
break;
case WindowMessage.MBUTTONDOWN:
HandleMButtonDown(handle, message, wParam, lParam);
break;
case WindowMessage.RBUTTONDOWN:
HandleRButtonDown(handle, message, wParam, lParam);
break;
case WindowMessage.XBUTTONDOWN:
HandleXButtonDown(handle, message, wParam, lParam);
break;
case WindowMessage.LBUTTONUP:
HandleLButtonUp(handle, message, wParam, lParam);
break;
case WindowMessage.MBUTTONUP:
HandleMButtonUp(handle, message, wParam, lParam);
break;
case WindowMessage.RBUTTONUP:
HandleRButtonUp(handle, message, wParam, lParam);
break;
case WindowMessage.XBUTTONUP:
HandleXButtonUp(handle, message, wParam, lParam);
break;
// Keyboard events:
case WindowMessage.KEYDOWN:
case WindowMessage.KEYUP:
case WindowMessage.SYSKEYDOWN:
case WindowMessage.SYSKEYUP:
HandleKeyboard(handle, message, wParam, lParam);
return IntPtr.Zero;
case WindowMessage.SYSCHAR:
return IntPtr.Zero;
case WindowMessage.KILLFOCUS:
HandleKillFocus(handle, message, wParam, lParam);
break;
#endregion
#region Creation / Destruction events
case WindowMessage.CREATE:
HandleCreate(handle, message, wParam, lParam);
break;
case WindowMessage.CLOSE:
HandleClose(handle, message, wParam, lParam);
return IntPtr.Zero;
case WindowMessage.DESTROY:
HandleDestroy(handle, message, wParam, lParam);
break; break;
#endregion #endregion
@ -1117,34 +1249,35 @@ namespace OpenTK.Platform.Windows
WindowState state = WindowState; WindowState state = WindowState;
ResetWindowState(); ResetWindowState();
WindowStyle style = WindowStyle.ClipChildren | WindowStyle.ClipSiblings; WindowStyle old_style = WindowStyle.ClipChildren | WindowStyle.ClipSiblings;
WindowStyle new_style = old_style;
switch (value) switch (value)
{ {
case WindowBorder.Resizable: case WindowBorder.Resizable:
style |= WindowStyle.OverlappedWindow; new_style |= WindowStyle.OverlappedWindow;
break; break;
case WindowBorder.Fixed: case WindowBorder.Fixed:
style |= WindowStyle.OverlappedWindow & new_style |= WindowStyle.OverlappedWindow &
~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox | WindowStyle.SizeBox); ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox | WindowStyle.SizeBox);
break; break;
case WindowBorder.Hidden: case WindowBorder.Hidden:
style |= WindowStyle.Popup; new_style |= WindowStyle.Popup;
break; break;
} }
// Make sure client size doesn't change when changing the border style. // Make sure client size doesn't change when changing the border style.
Size client_size = ClientSize; Size client_size = ClientSize;
Win32Rectangle rect = Win32Rectangle.From(client_size); Win32Rectangle rect = Win32Rectangle.From(client_size);
Functions.AdjustWindowRectEx(ref rect, style, false, ParentStyleEx); Functions.AdjustWindowRectEx(ref rect, new_style, false, ParentStyleEx);
// This avoids leaving garbage on the background window. // This avoids leaving garbage on the background window.
if (was_visible) if (was_visible)
Visible = false; Visible = false;
Functions.SetWindowLong(window.Handle, GetWindowLongOffsets.STYLE, (IntPtr)(int)style); Functions.SetWindowLong(window.Handle, GetWindowLongOffsets.STYLE, (IntPtr)(int)new_style);
Functions.SetWindowPos(window.Handle, IntPtr.Zero, 0, 0, rect.Width, rect.Height, Functions.SetWindowPos(window.Handle, IntPtr.Zero, 0, 0, rect.Width, rect.Height,
SetWindowPosFlags.NOMOVE | SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOMOVE | SetWindowPosFlags.NOZORDER |
SetWindowPosFlags.FRAMECHANGED); SetWindowPosFlags.FRAMECHANGED);
@ -1157,7 +1290,23 @@ namespace OpenTK.Platform.Windows
WindowState = state; WindowState = state;
WindowBorderChanged(this, EventArgs.Empty); // Workaround for github issues #33 and #34,
// where WindowMessage.STYLECHANGED is not
// delivered when running on Mono/Windows.
if (Configuration.RunningOnMono)
{
StyleStruct style = new StyleStruct();
style.New = new_style;
style.Old = old_style;
unsafe
{
HandleStyleChanged(
window.Handle,
WindowMessage.STYLECHANGED,
new IntPtr((int)(GWL.STYLE | GWL.EXSTYLE)),
new IntPtr(&style));
}
}
} }
} }