From: Olle Håkansson Date: Sun, 20 Apr 2014 17:56:23 +0000 (+0200) Subject: Better fullscreen handling. X-Git-Tag: 2.0-0~188^2~16 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=63d0d057c55b52871ab217867a9291135bcc918e;p=platform%2Fcore%2Fcsapi%2Fopentk.git Better fullscreen handling. --- diff --git a/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs index c21d415..1e38c57 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonBindings/QuartzDisplayServicesAPI.cs @@ -84,9 +84,18 @@ namespace OpenTK.Platform.MacOS.Carbon [DllImport(appServices,EntryPoint="CGDisplayCapture")] internal static extern CGDisplayErr DisplayCapture(IntPtr display); + [DllImport(appServices,EntryPoint="CGCaptureAllDisplays")] + internal static extern CGDisplayErr CaptureAllDisplays(); + + [DllImport(appServices,EntryPoint="CGShieldingWindowLevel")] + internal static extern uint ShieldingWindowLevel(); + [DllImport(appServices,EntryPoint="CGDisplayRelease")] internal static extern CGDisplayErr DisplayRelease(IntPtr display); + [DllImport(appServices,EntryPoint="CGReleaseAllDisplays")] + internal static extern CGDisplayErr DisplayReleaseAll(); + [DllImport(appServices, EntryPoint = "CGDisplayAvailableModes")] internal static extern IntPtr DisplayAvailableModes(IntPtr display); diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationPresentationOptions.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationPresentationOptions.cs index dbc349b..865f2a9 100755 --- a/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationPresentationOptions.cs +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSApplicationPresentationOptions.cs @@ -1,6 +1,6 @@ namespace OpenTK.Platform.MacOS { - public enum NSApplicationPresentationOptions + enum NSApplicationPresentationOptions { Default = 0, AutoHideDock = 1, diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSEventModifierMask.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSEventModifierMask.cs index e889f6c..55fc51b 100755 --- a/Source/OpenTK/Platform/MacOS/Cocoa/NSEventModifierMask.cs +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSEventModifierMask.cs @@ -3,7 +3,7 @@ namespace OpenTK.Platform.MacOS { [Flags] - public enum NSEventModifierMask : uint + enum NSEventModifierMask : uint { AlphaShiftKeyMask = 65536U, ShiftKeyMask = 131072U, diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSEventType.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSEventType.cs index a96e018..28d4eda 100755 --- a/Source/OpenTK/Platform/MacOS/Cocoa/NSEventType.cs +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSEventType.cs @@ -1,6 +1,6 @@ namespace OpenTK.Platform.MacOS { - public enum NSEventType + enum NSEventType { LeftMouseDown = 1, LeftMouseUp = 2, diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSTrackingAreaOptions.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSTrackingAreaOptions.cs index 7ad420f..f146acf 100755 --- a/Source/OpenTK/Platform/MacOS/Cocoa/NSTrackingAreaOptions.cs +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSTrackingAreaOptions.cs @@ -3,7 +3,7 @@ namespace OpenTK.Platform.MacOS { [Flags] - public enum NSTrackingAreaOptions + enum NSTrackingAreaOptions { MouseEnteredAndExited = 1, MouseMoved = 2, diff --git a/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs b/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs index 95401c5..0546e9e 100644 --- a/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs +++ b/Source/OpenTK/Platform/MacOS/CocoaNativeWindow.cs @@ -32,7 +32,7 @@ namespace OpenTK.Platform.MacOS static readonly IntPtr selContentView = Selector.Get("contentView"); static readonly IntPtr selConvertRectFromScreen = Selector.Get("convertRectFromScreen:"); static readonly IntPtr selConvertRectToScreen = Selector.Get("convertRectToScreen:"); - static readonly IntPtr selPerformClose = Selector.Get("performClose:"); + //static readonly IntPtr selPerformClose = Selector.Get("performClose:"); static readonly IntPtr selClose = Selector.Get("close"); static readonly IntPtr selTitle = Selector.Get("title"); static readonly IntPtr selSetTitle = Selector.Get("setTitle:"); @@ -63,15 +63,19 @@ namespace OpenTK.Platform.MacOS static readonly IntPtr selScrollingDeltaY = Selector.Get("scrollingDeltaY"); static readonly IntPtr selButtonNumber = Selector.Get("buttonNumber"); static readonly IntPtr selSetStyleMask = Selector.Get("setStyleMask:"); - static readonly IntPtr selIsInFullScreenMode = Selector.Get("isInFullScreenMode"); static readonly IntPtr selIsMiniaturized = Selector.Get("isMiniaturized"); static readonly IntPtr selIsZoomed = Selector.Get("isZoomed"); static readonly IntPtr selMiniaturize = Selector.Get("miniaturize:"); static readonly IntPtr selDeminiaturize = Selector.Get("deminiaturize:"); static readonly IntPtr selZoom = Selector.Get("zoom:"); - static readonly IntPtr selExitFullScreenModeWithOptions = Selector.Get("exitFullScreenModeWithOptions:"); - static readonly IntPtr selEnterFullScreenModeWithOptions = Selector.Get("enterFullScreenMode:withOptions:"); - + static readonly IntPtr selLevel = Selector.Get("level"); + static readonly IntPtr selSetLevel = Selector.Get("setLevel:"); + static readonly IntPtr selPresentationOptions = Selector.Get("presentationOptions"); + static readonly IntPtr selSetPresentationOptions = Selector.Get("setPresentationOptions:"); + //static readonly IntPtr selIsInFullScreenMode = Selector.Get("isInFullScreenMode"); + //static readonly IntPtr selExitFullScreenModeWithOptions = Selector.Get("exitFullScreenModeWithOptions:"); + //static readonly IntPtr selEnterFullScreenModeWithOptions = Selector.Get("enterFullScreenMode:withOptions:"); + static readonly IntPtr NSDefaultRunLoopMode; static readonly IntPtr NSCursor; @@ -95,11 +99,20 @@ namespace OpenTK.Platform.MacOS private OpenTK.Input.KeyboardKeyEventArgs keyArgs = new OpenTK.Input.KeyboardKeyEventArgs(); private KeyPressEventArgs keyPressArgs = new KeyPressEventArgs((char)0); + bool exclusiveFullscreen = true; + bool fullscreenMode; + Rectangle preFullscreenSize; + int preFullscreenLevel; + string preFullscreenTitle; + public CocoaNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) { // Create the window class windowClass = Class.AllocateClass("OpenTKWindow", "NSWindow"); Class.RegisterMethod(windowClass, new WindowDidResizeDelegate(WindowDidResize), "windowDidResize:", "v@:@"); + Class.RegisterMethod(windowClass, new WindowDidMoveDelegate(WindowDidMove), "windowDidMove:", "v@:@"); + Class.RegisterMethod(windowClass, new WindowDidBecomeKeyDelegate(WindowDidBecomeKey), "windowDidBecomeKey:", "v@:@"); + Class.RegisterMethod(windowClass, new WindowDidResignKeyDelegate(WindowDidResignKey), "windowDidResignKey:", "v@:@"); Class.RegisterMethod(windowClass, new WindowShouldCloseDelegate(WindowShouldClose), "windowShouldClose:", "b@:@"); Class.RegisterMethod(windowClass, new AcceptsFirstResponderDelegate(AcceptsFirstResponder), "acceptsFirstResponder", "b@:"); Class.RegisterMethod(windowClass, new CanBecomeKeyWindowDelegate(CanBecomeKeyWindow), "canBecomeKeyWindow", "b@:"); @@ -115,18 +128,21 @@ namespace OpenTK.Platform.MacOS IntPtr windowPtr; windowPtr = Cocoa.SendIntPtr(windowClass, Selector.Alloc); windowPtr = Cocoa.SendIntPtr(windowPtr, Selector.Get("initWithContentRect:styleMask:backing:defer:"), contentRect, (int)style, (int)bufferingType, false); + windowInfo = new CocoaWindowInfo(windowPtr); // Set up behavior Cocoa.SendIntPtr(windowPtr, Selector.Get("setDelegate:"), windowPtr); // The window class acts as its own delegate Cocoa.SendVoid(windowPtr, Selector.Get("cascadeTopLeftFromPoint:"), new System.Drawing.PointF(20, 20)); - Cocoa.SendVoid(windowPtr, Selector.Get("setTitle:"), Cocoa.ToNSString(title)); Cocoa.SendVoid(windowPtr, Selector.Get("makeKeyAndOrderFront:"), IntPtr.Zero); + SetTitle(title, false); - windowInfo = new CocoaWindowInfo(windowPtr); ResetTrackingArea(); } delegate void WindowDidResizeDelegate(IntPtr self, IntPtr cmd, IntPtr notification); + delegate void WindowDidMoveDelegate(IntPtr self, IntPtr cmd, IntPtr notification); + delegate void WindowDidBecomeKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification); + delegate void WindowDidResignKeyDelegate(IntPtr self, IntPtr cmd, IntPtr notification); delegate bool WindowShouldCloseDelegate(IntPtr self, IntPtr cmd, IntPtr sender); delegate bool AcceptsFirstResponderDelegate(IntPtr self, IntPtr cmd); delegate bool CanBecomeKeyWindowDelegate(IntPtr self, IntPtr cmd); @@ -136,6 +152,22 @@ namespace OpenTK.Platform.MacOS { ResetTrackingArea(); GraphicsContext.CurrentContext.Update(windowInfo); + Resize(this, EventArgs.Empty); + } + + private void WindowDidMove(IntPtr self, IntPtr cmd, IntPtr notification) + { + Move(this, EventArgs.Empty); + } + + private void WindowDidBecomeKey(IntPtr self, IntPtr cmd, IntPtr notification) + { + FocusedChanged(this, EventArgs.Empty); + } + + private void WindowDidResignKey(IntPtr self, IntPtr cmd, IntPtr notification) + { + FocusedChanged(this, EventArgs.Empty); } private bool WindowShouldClose(IntPtr self, IntPtr cmd, IntPtr sender) @@ -188,17 +220,17 @@ namespace OpenTK.Platform.MacOS { // PerformClose is equivalent to pressing the close-button, which // does not work in a borderless window. Handle this special case. - if (WindowBorder == WindowBorder.Hidden) + //if (WindowBorder == WindowBorder.Hidden) { if (WindowShouldClose(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { Cocoa.SendVoid(windowInfo.Handle, selClose); } } - else - { - Cocoa.SendVoid(windowInfo.Handle, selPerformClose, windowInfo.Handle); - } +// else +// { +// Cocoa.SendVoid(windowInfo.Handle, selPerformClose, windowInfo.Handle); +// } } private KeyModifiers GetModifiers(NSEventModifierMask mask) @@ -395,8 +427,7 @@ namespace OpenTK.Platform.MacOS } set { - Cocoa.SendIntPtr(windowInfo.Handle, selSetTitle, Cocoa.ToNSString(value)); - TitleChanged(this, EventArgs.Empty); + SetTitle(value, true); } } @@ -442,8 +473,19 @@ namespace OpenTK.Platform.MacOS var ws = WindowState; if (ws == WindowState.Fullscreen) { - IntPtr nsDictionary = Cocoa.SendIntPtr(Cocoa.SendIntPtr(Cocoa.SendIntPtr(Class.Get("NSDictionary"), Selector.Alloc), Selector.Init), Selector.Autorelease); - Cocoa.SendVoid(windowInfo.ViewHandle, selExitFullScreenModeWithOptions, nsDictionary); + //Cocoa.SendVoid(windowInfo.ViewHandle, selExitFullScreenModeWithOptions, IntPtr.Zero); + + SetMenuVisible(true); + if (exclusiveFullscreen) + { + OpenTK.Platform.MacOS.Carbon.CG.DisplayReleaseAll(); + Cocoa.SendVoid(windowInfo.Handle, selSetLevel, preFullscreenLevel); + } + + Cocoa.SendVoid(windowInfo.Handle, selSetStyleMask, (uint)GetStyleMask(windowBorder)); + Bounds = preFullscreenSize; + SetTitle(preFullscreenTitle, false); // For some reason, the title is lost + fullscreenMode = false; } else if (ws == WindowState.Maximized) { @@ -459,7 +501,7 @@ namespace OpenTK.Platform.MacOS { get { - if (Cocoa.SendBool(windowInfo.ViewHandle, selIsInFullScreenMode)) + if (fullscreenMode) return WindowState.Fullscreen; if (Cocoa.SendBool(windowInfo.Handle, selIsMiniaturized)) @@ -480,30 +522,46 @@ namespace OpenTK.Platform.MacOS 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); - } +// 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); + + fullscreenMode = true; + preFullscreenSize = Bounds; + preFullscreenTitle = Title; + var screenFrame = GetCurrentScreenFrame(); + + if (exclusiveFullscreen) + { + preFullscreenLevel = Cocoa.SendInt(windowInfo.Handle, selLevel); + var windowLevel = OpenTK.Platform.MacOS.Carbon.CG.ShieldingWindowLevel(); + + OpenTK.Platform.MacOS.Carbon.CG.CaptureAllDisplays(); + Cocoa.SendVoid(windowInfo.Handle, selSetLevel, windowLevel); + } - if (value == WindowState.Maximized) + Cocoa.SendVoid(windowInfo.Handle, selSetStyleMask, (uint)NSWindowStyle.Borderless); + Bounds = new Rectangle((int)screenFrame.X, (int)screenFrame.Y, (int)screenFrame.Width, (int)screenFrame.Height); + SetMenuVisible(false); + } + else if (value == WindowState.Maximized) { Cocoa.SendVoid(windowInfo.Handle, selZoom, windowInfo.Handle); } - - if (value == WindowState.Minimized) + else if (value == WindowState.Minimized) { Cocoa.SendVoid(windowInfo.Handle, selMiniaturize, windowInfo.Handle); } @@ -544,11 +602,11 @@ namespace OpenTK.Platform.MacOS get { var r = Cocoa.SendRect(windowInfo.Handle, selFrame); - return new Rectangle((int)r.X, (int)(GetCurrentScreenFrame().Height - r.Y), (int)r.Width, (int)r.Height); + return new Rectangle((int)r.X, (int)r.Y, (int)r.Width, (int)r.Height); } set { - Cocoa.SendVoid(windowInfo.Handle, selSetFrame, new RectangleF(value.X, GetCurrentScreenFrame().Height - value.Y, value.Width, value.Height), true); + Cocoa.SendVoid(windowInfo.Handle, selSetFrame, new RectangleF(value.X, value.Y, value.Width, value.Height), true); } } @@ -746,5 +804,31 @@ namespace OpenTK.Platform.MacOS { Cocoa.SendVoid(NSCursor, visible ? selUnhide : selHide); } + + private void SetMenuVisible(bool visible) + { + var options = (NSApplicationPresentationOptions)Cocoa.SendInt(NSApplication.Handle, selPresentationOptions); + var changedOptions = NSApplicationPresentationOptions.HideMenuBar | NSApplicationPresentationOptions.HideDock; + + if (!visible) + { + options |= changedOptions; + } + else + { + options &= ~changedOptions; + } + + Cocoa.SendVoid(NSApplication.Handle, selSetPresentationOptions, (int)options); + } + + private void SetTitle(string newTitle, bool callEvent) + { + Cocoa.SendIntPtr(windowInfo.Handle, selSetTitle, Cocoa.ToNSString(newTitle)); + if (callEvent) + { + TitleChanged(this, EventArgs.Empty); + } + } } }