Much improved handling of window/border states.

This commit is contained in:
Olle Håkansson 2014-04-22 21:29:03 +02:00 committed by thefiddler
parent df6caa3cbb
commit 4573db2ceb

View file

@ -28,7 +28,7 @@ namespace OpenTK.Platform.MacOS
static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:"); static readonly IntPtr selNextEventMatchingMask = Selector.Get("nextEventMatchingMask:untilDate:inMode:dequeue:");
static readonly IntPtr selSendEvent = Selector.Get("sendEvent:"); static readonly IntPtr selSendEvent = Selector.Get("sendEvent:");
static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows"); //static readonly IntPtr selUpdateWindows = Selector.Get("updateWindows");
static readonly IntPtr selContentView = Selector.Get("contentView"); static readonly IntPtr selContentView = Selector.Get("contentView");
static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:"); static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:");
static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:"); static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:");
@ -41,6 +41,7 @@ namespace OpenTK.Platform.MacOS
static readonly IntPtr selIsVisible = Selector.Get("isVisible"); static readonly IntPtr selIsVisible = Selector.Get("isVisible");
static readonly IntPtr selSetIsVisible = Selector.Get("setIsVisible:"); static readonly IntPtr selSetIsVisible = Selector.Get("setIsVisible:");
static readonly IntPtr selFrame = Selector.Get("frame"); static readonly IntPtr selFrame = Selector.Get("frame");
static readonly IntPtr selVisibleFrame = Selector.Get("visibleFrame");
static readonly IntPtr selBounds = Selector.Get("bounds"); static readonly IntPtr selBounds = Selector.Get("bounds");
static readonly IntPtr selScreen = Selector.Get("screen"); static readonly IntPtr selScreen = Selector.Get("screen");
static readonly IntPtr selSetFrame = Selector.Get("setFrame:display:"); static readonly IntPtr selSetFrame = Selector.Get("setFrame:display:");
@ -64,10 +65,12 @@ namespace OpenTK.Platform.MacOS
static readonly IntPtr selButtonNumber = Selector.Get("buttonNumber"); static readonly IntPtr selButtonNumber = Selector.Get("buttonNumber");
static readonly IntPtr selSetStyleMask = Selector.Get("setStyleMask:"); static readonly IntPtr selSetStyleMask = Selector.Get("setStyleMask:");
static readonly IntPtr selStyleMask = Selector.Get("styleMask"); static readonly IntPtr selStyleMask = Selector.Get("styleMask");
// static readonly IntPtr selIsMiniaturized = Selector.Get("isMiniaturized"); //static readonly IntPtr selIsMiniaturized = Selector.Get("isMiniaturized");
// static readonly IntPtr selIsZoomed = Selector.Get("isZoomed"); //static readonly IntPtr selIsZoomed = Selector.Get("isZoomed");
static readonly IntPtr selPerformMiniaturize = Selector.Get("performMiniaturize:");
static readonly IntPtr selMiniaturize = Selector.Get("miniaturize:"); static readonly IntPtr selMiniaturize = Selector.Get("miniaturize:");
static readonly IntPtr selDeminiaturize = Selector.Get("deminiaturize:"); static readonly IntPtr selDeminiaturize = Selector.Get("deminiaturize:");
//static readonly IntPtr selPerformZoom = Selector.Get("performZoom:");
static readonly IntPtr selZoom = Selector.Get("zoom:"); static readonly IntPtr selZoom = Selector.Get("zoom:");
static readonly IntPtr selLevel = Selector.Get("level"); static readonly IntPtr selLevel = Selector.Get("level");
static readonly IntPtr selSetLevel = Selector.Get("setLevel:"); static readonly IntPtr selSetLevel = Selector.Get("setLevel:");
@ -96,14 +99,17 @@ namespace OpenTK.Platform.MacOS
private System.Drawing.Icon icon; private System.Drawing.Icon icon;
private LegacyInputDriver inputDriver = new LegacyInputDriver(); private LegacyInputDriver inputDriver = new LegacyInputDriver();
private WindowBorder windowBorder = WindowBorder.Resizable; private WindowBorder windowBorder = WindowBorder.Resizable;
private Nullable<WindowBorder> deferredWindowBorder;
private Nullable<WindowBorder> previousWindowBorder;
private WindowState windowState = WindowState.Normal; private WindowState windowState = WindowState.Normal;
private MacOSKeyMap keyMap = new MacOSKeyMap(); private MacOSKeyMap keyMap = new MacOSKeyMap();
private OpenTK.Input.KeyboardKeyEventArgs keyArgs = new OpenTK.Input.KeyboardKeyEventArgs(); private OpenTK.Input.KeyboardKeyEventArgs keyArgs = new OpenTK.Input.KeyboardKeyEventArgs();
private KeyPressEventArgs keyPressArgs = new KeyPressEventArgs((char)0); private KeyPressEventArgs keyPressArgs = new KeyPressEventArgs((char)0);
private string title; private string title;
private RectangleF normalBounds; private RectangleF previousBounds;
private int normalLevel; private int normalLevel;
private bool shouldClose; private bool shouldClose;
private int suppressResize;
private const bool exclusiveFullscreen = false; private const bool exclusiveFullscreen = false;
@ -119,7 +125,6 @@ namespace OpenTK.Platform.MacOS
Class.RegisterMethod(windowClass, new WindowDidMiniaturizeDelegate(WindowDidMiniaturize), "windowDidMiniaturize:", "v@:@"); Class.RegisterMethod(windowClass, new WindowDidMiniaturizeDelegate(WindowDidMiniaturize), "windowDidMiniaturize:", "v@:@");
Class.RegisterMethod(windowClass, new WindowDidDeminiaturizeDelegate(WindowDidDeminiaturize), "windowDidDeminiaturize:", "v@:@"); Class.RegisterMethod(windowClass, new WindowDidDeminiaturizeDelegate(WindowDidDeminiaturize), "windowDidDeminiaturize:", "v@:@");
Class.RegisterMethod(windowClass, new WindowShouldZoomToFrameDelegate(WindowShouldZoomToFrame), "windowShouldZoom:toFrame:", "b@:@{NSRect={NSPoint=ff}{NSSize=ff}}"); Class.RegisterMethod(windowClass, new WindowShouldZoomToFrameDelegate(WindowShouldZoomToFrame), "windowShouldZoom:toFrame:", "b@:@{NSRect={NSPoint=ff}{NSSize=ff}}");
Class.RegisterMethod(windowClass, new WindowShouldCloseDelegate(WindowShouldClose), "windowShouldClose:", "b@:@"); Class.RegisterMethod(windowClass, new WindowShouldCloseDelegate(WindowShouldClose), "windowShouldClose:", "b@:@");
Class.RegisterMethod(windowClass, new AcceptsFirstResponderDelegate(AcceptsFirstResponder), "acceptsFirstResponder", "b@:"); Class.RegisterMethod(windowClass, new AcceptsFirstResponderDelegate(AcceptsFirstResponder), "acceptsFirstResponder", "b@:");
Class.RegisterMethod(windowClass, new CanBecomeKeyWindowDelegate(CanBecomeKeyWindow), "canBecomeKeyWindow", "b@:"); Class.RegisterMethod(windowClass, new CanBecomeKeyWindowDelegate(CanBecomeKeyWindow), "canBecomeKeyWindow", "b@:");
@ -171,7 +176,9 @@ namespace OpenTK.Platform.MacOS
ResetTrackingArea(); ResetTrackingArea();
} }
GraphicsContext.CurrentContext.Update(windowInfo); GraphicsContext.CurrentContext.Update(windowInfo);
Resize(this, EventArgs.Empty);
if (suppressResize == 0)
Resize(this, EventArgs.Empty);
} }
private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification) private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification)
@ -221,8 +228,8 @@ namespace OpenTK.Platform.MacOS
} }
else else
{ {
normalBounds = InternalBounds; previousBounds = InternalBounds;
Cocoa.SendVoid(windowInfo.Handle, selSetStyleMask, (uint)GetStyleMask(WindowBorder.Fixed)); previousWindowBorder = WindowBorder;
InternalBounds = toFrame; InternalBounds = toFrame;
windowState = WindowState.Maximized; windowState = WindowState.Maximized;
@ -550,10 +557,9 @@ namespace OpenTK.Platform.MacOS
private void RestoreWindowState() private void RestoreWindowState()
{ {
suppressResize++;
if (windowState == WindowState.Fullscreen) if (windowState == WindowState.Fullscreen)
{ {
//Cocoa.SendVoid(windowInfo.ViewHandle, selExitFullScreenModeWithOptions, IntPtr.Zero);
SetMenuVisible(true); SetMenuVisible(true);
if (exclusiveFullscreen) if (exclusiveFullscreen)
{ {
@ -561,13 +567,13 @@ namespace OpenTK.Platform.MacOS
Cocoa.SendVoid(windowInfo.Handle, selSetLevel, normalLevel); Cocoa.SendVoid(windowInfo.Handle, selSetLevel, normalLevel);
} }
UpdateWindowBorder(); RestoreBorder();
InternalBounds = normalBounds; InternalBounds = previousBounds;
} }
else if (windowState == WindowState.Maximized) else if (windowState == WindowState.Maximized)
{ {
UpdateWindowBorder(); RestoreBorder();
InternalBounds = normalBounds; InternalBounds = previousBounds;
} }
else if (windowState == WindowState.Minimized) else if (windowState == WindowState.Minimized)
{ {
@ -575,6 +581,29 @@ namespace OpenTK.Platform.MacOS
} }
windowState = WindowState.Normal; windowState = WindowState.Normal;
suppressResize--;
}
private void HideBorder()
{
suppressResize++;
SetWindowBorder(WindowBorder.Hidden);
ProcessEvents();
suppressResize--;
}
private void RestoreBorder()
{
suppressResize++;
SetWindowBorder(
deferredWindowBorder.HasValue ? deferredWindowBorder.Value :
previousWindowBorder.HasValue ? previousWindowBorder.Value :
windowBorder);
ProcessEvents();
suppressResize--;
deferredWindowBorder = null;
previousWindowBorder = null;
} }
public WindowState WindowState public WindowState WindowState
@ -593,25 +622,6 @@ namespace OpenTK.Platform.MacOS
if (value == WindowState.Fullscreen) if (value == WindowState.Fullscreen)
{ {
// NSApplicationPresentationOptions options =
// NSApplicationPresentationOptions.DisableAppleMenu |
// NSApplicationPresentationOptions.HideMenuBar |
// NSApplicationPresentationOptions.HideDock;
//
// // "Exclusive fullscreen"?
// //NSApplicationPresentationOptions.DisableProcessSwitching;
//
// var obj = Cocoa.SendIntPtr(Class.Get("NSNumber"), Selector.Get("numberWithUnsignedLong:"), (ulong)options);
// var key = Cocoa.ToNSString("NSFullScreenModeApplicationPresentationOptions");
//
// var nsDictionary = Cocoa.SendIntPtr(Class.Get("NSDictionary"), Selector.Alloc);
// nsDictionary = Cocoa.SendIntPtr(nsDictionary, Selector.Get("initWithObjectsAndKeys:"), obj, key, IntPtr.Zero);
// nsDictionary = Cocoa.SendIntPtr(nsDictionary, Selector.Autorelease);
//
// Cocoa.SendVoid(windowInfo.ViewHandle, selEnterFullScreenModeWithOptions, GetCurrentScreen(), nsDictionary);
normalBounds = InternalBounds;
if (exclusiveFullscreen) if (exclusiveFullscreen)
{ {
normalLevel = Cocoa.SendInt(windowInfo.Handle, selLevel); normalLevel = Cocoa.SendInt(windowInfo.Handle, selLevel);
@ -621,16 +631,19 @@ namespace OpenTK.Platform.MacOS
Cocoa.SendVoid(windowInfo.Handle, selSetLevel, windowLevel); Cocoa.SendVoid(windowInfo.Handle, selSetLevel, windowLevel);
} }
Cocoa.SendVoid(windowInfo.Handle, selSetStyleMask, (uint)NSWindowStyle.Borderless); previousBounds = InternalBounds;
InternalBounds = GetCurrentScreenFrame(); previousWindowBorder = WindowBorder;
SetMenuVisible(false); SetMenuVisible(false);
HideBorder();
InternalBounds = GetCurrentScreenFrame();
windowState = value; windowState = value;
WindowStateChanged(this, EventArgs.Empty); WindowStateChanged(this, EventArgs.Empty);
} }
else if (value == WindowState.Maximized) else if (value == WindowState.Maximized)
{ {
Cocoa.SendVoid(windowInfo.Handle, selZoom, windowInfo.Handle); WindowShouldZoomToFrame(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, GetCurrentScreenVisibleFrame());
} }
else if (value == WindowState.Minimized) else if (value == WindowState.Minimized)
{ {
@ -640,6 +653,7 @@ namespace OpenTK.Platform.MacOS
{ {
windowState = value; windowState = value;
WindowStateChanged(this, EventArgs.Empty); WindowStateChanged(this, EventArgs.Empty);
Resize(this, EventArgs.Empty);
} }
} }
} }
@ -652,12 +666,27 @@ namespace OpenTK.Platform.MacOS
} }
set set
{ {
windowBorder = value; // Do not allow border changes during fullscreen mode.
UpdateWindowBorder(); if (windowState == WindowState.Fullscreen || windowState == WindowState.Maximized)
{
deferredWindowBorder = value;
return;
}
if (windowBorder == value)
return;
SetWindowBorder(value);
WindowBorderChanged(this, EventArgs.Empty); WindowBorderChanged(this, EventArgs.Empty);
} }
} }
private void SetWindowBorder(WindowBorder windowBorder)
{
this.windowBorder = windowBorder;
UpdateWindowBorder();
}
private static NSWindowStyle GetStyleMask(WindowBorder windowBorder) private static NSWindowStyle GetStyleMask(WindowBorder windowBorder)
{ {
switch (windowBorder) switch (windowBorder)
@ -885,6 +914,11 @@ namespace OpenTK.Platform.MacOS
return Cocoa.SendRect(GetCurrentScreen(), selFrame); return Cocoa.SendRect(GetCurrentScreen(), selFrame);
} }
private RectangleF GetCurrentScreenVisibleFrame()
{
return Cocoa.SendRect(GetCurrentScreen(), selVisibleFrame);
}
private void SetCursorVisible(bool visible) private void SetCursorVisible(bool visible)
{ {
// Problem: Unlike the PC version, you can move the mouse out of the window. // Problem: Unlike the PC version, you can move the mouse out of the window.