mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 02:42:02 +01:00
internal/ui: remove Cgo on darwin in ui_glfw_darwin.go (#2329)
Updates #1162
This commit is contained in:
parent
45b2bd7b2b
commit
043397c20e
@ -26,6 +26,11 @@ var (
|
|||||||
class_NSMethodSignature = objc.GetClass("NSMethodSignature")
|
class_NSMethodSignature = objc.GetClass("NSMethodSignature")
|
||||||
class_NSAutoreleasePool = objc.GetClass("NSAutoreleasePool")
|
class_NSAutoreleasePool = objc.GetClass("NSAutoreleasePool")
|
||||||
class_NSString = objc.GetClass("NSString")
|
class_NSString = objc.GetClass("NSString")
|
||||||
|
class_NSProcessInfo = objc.GetClass("NSProcessInfo")
|
||||||
|
class_NSColor = objc.GetClass("NSColor")
|
||||||
|
class_NSWindow = objc.GetClass("NSWindow")
|
||||||
|
class_NSView = objc.GetClass("NSView")
|
||||||
|
class_NSScreen = objc.GetClass("NSScreen")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -38,23 +43,165 @@ var (
|
|||||||
sel_setArgumentAtIndex = objc.RegisterName("setArgument:atIndex:")
|
sel_setArgumentAtIndex = objc.RegisterName("setArgument:atIndex:")
|
||||||
sel_getReturnValue = objc.RegisterName("getReturnValue:")
|
sel_getReturnValue = objc.RegisterName("getReturnValue:")
|
||||||
sel_invoke = objc.RegisterName("invoke")
|
sel_invoke = objc.RegisterName("invoke")
|
||||||
|
sel_invokeWithTarget = objc.RegisterName("invokeWithTarget:")
|
||||||
sel_instanceMethodSignatureForSelector = objc.RegisterName("instanceMethodSignatureForSelector:")
|
sel_instanceMethodSignatureForSelector = objc.RegisterName("instanceMethodSignatureForSelector:")
|
||||||
sel_signatureWithObjCTypes = objc.RegisterName("signatureWithObjCTypes:")
|
sel_signatureWithObjCTypes = objc.RegisterName("signatureWithObjCTypes:")
|
||||||
sel_initWithUTF8String = objc.RegisterName("initWithUTF8String:")
|
sel_initWithUTF8String = objc.RegisterName("initWithUTF8String:")
|
||||||
sel_UTF8String = objc.RegisterName("UTF8String")
|
sel_UTF8String = objc.RegisterName("UTF8String")
|
||||||
sel_length = objc.RegisterName("length")
|
sel_length = objc.RegisterName("length")
|
||||||
|
sel_processInfo = objc.RegisterName("processInfo")
|
||||||
|
sel_isOperatingSystemAtLeastVersion = objc.RegisterName("isOperatingSystemAtLeastVersion:")
|
||||||
|
sel_frame = objc.RegisterName("frame")
|
||||||
|
sel_contentView = objc.RegisterName("contentView")
|
||||||
|
sel_setBackgroundColor = objc.RegisterName("setBackgroundColor:")
|
||||||
|
sel_colorWithSRGBRedGreenBlueAlpha = objc.RegisterName("colorWithSRGBRed:green:blue:alpha:")
|
||||||
|
sel_setFrameSize = objc.RegisterName("setFrameSize:")
|
||||||
|
sel_object = objc.RegisterName("object")
|
||||||
|
sel_styleMask = objc.RegisterName("styleMask")
|
||||||
|
sel_setStyleMask = objc.RegisterName("setStyleMask:")
|
||||||
|
sel_mainScreen = objc.RegisterName("mainScreen")
|
||||||
|
sel_screen = objc.RegisterName("screen")
|
||||||
|
sel_isVisible = objc.RegisterName("isVisible")
|
||||||
|
sel_deviceDescription = objc.RegisterName("deviceDescription")
|
||||||
|
sel_objectForKey = objc.RegisterName("objectForKey:")
|
||||||
|
sel_unsignedIntValue = objc.RegisterName("unsignedIntValue")
|
||||||
)
|
)
|
||||||
|
|
||||||
type CGFloat float64
|
const NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7
|
||||||
|
|
||||||
|
const (
|
||||||
|
NSWindowStyleMaskResizable = 1 << 3
|
||||||
|
NSWindowStyleMaskFullScreen = 1 << 14
|
||||||
|
)
|
||||||
|
|
||||||
|
type CGFloat = float64
|
||||||
|
|
||||||
type CGSize struct {
|
type CGSize struct {
|
||||||
Width, Height CGFloat
|
Width, Height CGFloat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CGPoint struct {
|
||||||
|
X, Y float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type CGRect struct {
|
||||||
|
Origin CGPoint
|
||||||
|
Size CGSize
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSUInteger = uint
|
||||||
|
type NSInteger = int
|
||||||
|
|
||||||
|
type NSPoint = CGPoint
|
||||||
|
type NSRect = CGRect
|
||||||
|
type NSSize = CGSize
|
||||||
|
|
||||||
type NSError struct {
|
type NSError struct {
|
||||||
objc.ID
|
objc.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NSColor struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func NSColor_colorWithSRGBRedGreenBlueAlpha(red, green, blue, alpha CGFloat) (color NSColor) {
|
||||||
|
sig := NSMethodSignature_signatureWithObjCTypes("@@:ffff")
|
||||||
|
inv := NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetSelector(sel_colorWithSRGBRedGreenBlueAlpha)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&red), 2)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&green), 3)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&blue), 4)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&alpha), 5)
|
||||||
|
inv.InvokeWithTarget(objc.ID(class_NSColor))
|
||||||
|
inv.GetReturnValue(unsafe.Pointer(&color))
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSOperatingSystemVersion struct {
|
||||||
|
Major, Minor, Patch NSInteger
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSProcessInfo struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func NSProcessInfo_processInfo() NSProcessInfo {
|
||||||
|
return NSProcessInfo{objc.ID(class_NSProcessInfo).Send(sel_processInfo)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p NSProcessInfo) IsOperatingSystemAtLeastVersion(version NSOperatingSystemVersion) bool {
|
||||||
|
sig := NSMethodSignature_instanceMethodSignatureForSelector(objc.ID(class_NSProcessInfo), sel_isOperatingSystemAtLeastVersion)
|
||||||
|
inv := NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetTarget(p.ID)
|
||||||
|
inv.SetSelector(sel_isOperatingSystemAtLeastVersion)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&version), 2)
|
||||||
|
inv.Invoke()
|
||||||
|
var ret int
|
||||||
|
inv.GetReturnValue(unsafe.Pointer(&ret))
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSWindow struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) StyleMask() NSUInteger {
|
||||||
|
return NSUInteger(w.Send(sel_styleMask))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) SetStyleMask(styleMask NSUInteger) {
|
||||||
|
w.Send(sel_setStyleMask, styleMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) SetBackgroundColor(color NSColor) {
|
||||||
|
w.Send(sel_setBackgroundColor, color.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) IsVisibile() bool {
|
||||||
|
return w.Send(sel_isVisible) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) Screen() NSScreen {
|
||||||
|
return NSScreen{w.Send(sel_screen)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) Frame() NSRect {
|
||||||
|
sig := NSMethodSignature_instanceMethodSignatureForSelector(objc.ID(class_NSWindow), sel_frame)
|
||||||
|
inv := NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetTarget(w.ID)
|
||||||
|
inv.SetSelector(sel_frame)
|
||||||
|
inv.Invoke()
|
||||||
|
var rect NSRect
|
||||||
|
inv.GetReturnValue(unsafe.Pointer(&rect))
|
||||||
|
return rect
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w NSWindow) ContentView() NSView {
|
||||||
|
return NSView{w.Send(sel_contentView)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSView struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v NSView) SetFrameSize(size CGSize) {
|
||||||
|
sig := NSMethodSignature_instanceMethodSignatureForSelector(objc.ID(class_NSView), sel_setFrameSize)
|
||||||
|
inv := NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetSelector(sel_setFrameSize)
|
||||||
|
inv.SetArgumentAtIndex(unsafe.Pointer(&size), 2)
|
||||||
|
inv.InvokeWithTarget(v.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v NSView) Frame() NSRect {
|
||||||
|
sig := NSMethodSignature_instanceMethodSignatureForSelector(objc.ID(class_NSView), sel_frame)
|
||||||
|
inv := NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetSelector(sel_frame)
|
||||||
|
inv.InvokeWithTarget(v.ID)
|
||||||
|
var rect NSRect
|
||||||
|
inv.GetReturnValue(unsafe.Pointer(&rect))
|
||||||
|
return rect
|
||||||
|
}
|
||||||
|
|
||||||
// NSInvocation is being used to call functions that can't be called directly with purego.SyscallN.
|
// NSInvocation is being used to call functions that can't be called directly with purego.SyscallN.
|
||||||
// See the downsides of that function for what it cannot do.
|
// See the downsides of that function for what it cannot do.
|
||||||
type NSInvocation struct {
|
type NSInvocation struct {
|
||||||
@ -65,24 +212,28 @@ func NSInvocation_invocationWithMethodSignature(sig NSMethodSignature) NSInvocat
|
|||||||
return NSInvocation{objc.ID(class_NSInvocation).Send(sel_invocationWithMethodSignature, sig.ID)}
|
return NSInvocation{objc.ID(class_NSInvocation).Send(sel_invocationWithMethodSignature, sig.ID)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv NSInvocation) SetSelector(cmd objc.SEL) {
|
func (i NSInvocation) SetSelector(cmd objc.SEL) {
|
||||||
inv.Send(sel_setSelector, cmd)
|
i.Send(sel_setSelector, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv NSInvocation) SetTarget(target objc.ID) {
|
func (i NSInvocation) SetTarget(target objc.ID) {
|
||||||
inv.Send(sel_setTarget, target)
|
i.Send(sel_setTarget, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv NSInvocation) SetArgumentAtIndex(arg unsafe.Pointer, idx int) {
|
func (i NSInvocation) SetArgumentAtIndex(arg unsafe.Pointer, idx int) {
|
||||||
inv.Send(sel_setArgumentAtIndex, arg, idx)
|
i.Send(sel_setArgumentAtIndex, arg, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv NSInvocation) GetReturnValue(ret unsafe.Pointer) {
|
func (i NSInvocation) GetReturnValue(ret unsafe.Pointer) {
|
||||||
inv.Send(sel_getReturnValue, ret)
|
i.Send(sel_getReturnValue, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv NSInvocation) Invoke() {
|
func (i NSInvocation) Invoke() {
|
||||||
inv.Send(sel_invoke)
|
i.Send(sel_invoke)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i NSInvocation) InvokeWithTarget(target objc.ID) {
|
||||||
|
i.Send(sel_invokeWithTarget, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NSMethodSignature struct {
|
type NSMethodSignature struct {
|
||||||
@ -109,8 +260,8 @@ func NSAutoreleasePool_new() NSAutoreleasePool {
|
|||||||
return NSAutoreleasePool{objc.ID(class_NSAutoreleasePool).Send(sel_new)}
|
return NSAutoreleasePool{objc.ID(class_NSAutoreleasePool).Send(sel_new)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pool NSAutoreleasePool) Release() {
|
func (p NSAutoreleasePool) Release() {
|
||||||
pool.Send(sel_release)
|
p.Send(sel_release)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NSString struct {
|
type NSString struct {
|
||||||
@ -136,3 +287,39 @@ func (s NSString) String() string {
|
|||||||
header.Cap = header.Len
|
header.Cap = header.Len
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NSNotification struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NSNotification) Object() objc.ID {
|
||||||
|
return n.Send(sel_object)
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSScreen struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func NSScreen_mainScreen() NSScreen {
|
||||||
|
return NSScreen{objc.ID(class_NSScreen).Send(sel_mainScreen)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s NSScreen) DeviceDescription() NSDictionary {
|
||||||
|
return NSDictionary{s.Send(sel_deviceDescription)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSDictionary struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d NSDictionary) ObjectForKey(object objc.ID) objc.ID {
|
||||||
|
return d.Send(sel_objectForKey, object)
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSNumber struct {
|
||||||
|
objc.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NSNumber) UnsignedIntValue() uint {
|
||||||
|
return uint(n.Send(sel_unsignedIntValue))
|
||||||
|
}
|
||||||
|
@ -17,3 +17,7 @@ package glfw
|
|||||||
func (w *Window) GetCocoaWindow() uintptr {
|
func (w *Window) GetCocoaWindow() uintptr {
|
||||||
return uintptr(w.w.GetCocoaWindow())
|
return uintptr(w.w.GetCocoaWindow())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Monitor) GetCocoaMonitor() uintptr {
|
||||||
|
return m.m.GetCocoaMonitor()
|
||||||
|
}
|
||||||
|
@ -17,224 +17,107 @@
|
|||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
// #cgo CFLAGS: -x objective-c
|
|
||||||
// #cgo LDFLAGS: -framework AppKit
|
|
||||||
//
|
|
||||||
// #import <AppKit/AppKit.h>
|
|
||||||
//
|
|
||||||
// @interface EbitengineWindowDelegate : NSObject <NSWindowDelegate>
|
|
||||||
// @end
|
|
||||||
//
|
|
||||||
// @implementation EbitengineWindowDelegate {
|
|
||||||
// id<NSWindowDelegate> origDelegate_;
|
|
||||||
// bool origResizable_;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (instancetype)initWithOrigDelegate:(id<NSWindowDelegate>)origDelegate {
|
|
||||||
// self = [super init];
|
|
||||||
// if (self != nil) {
|
|
||||||
// origDelegate_ = origDelegate;
|
|
||||||
// }
|
|
||||||
// return self;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // The method set of origDelegate_ must sync with GLFWWindowDelegate's implementation.
|
|
||||||
// // See cocoa_window.m in GLFW.
|
|
||||||
// - (BOOL)windowShouldClose:(id)sender {
|
|
||||||
// return [origDelegate_ windowShouldClose:sender];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidResize:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidResize:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidMove:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidMove:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidMiniaturize:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidMiniaturize:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidDeminiaturize:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidDeminiaturize:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidBecomeKey:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidBecomeKey:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidResignKey:(NSNotification *)notification {
|
|
||||||
// [origDelegate_ windowDidResignKey:notification];
|
|
||||||
// }
|
|
||||||
// - (void)windowDidChangeOcclusionState:(NSNotification* )notification {
|
|
||||||
// [origDelegate_ windowDidChangeOcclusionState:notification];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)pushResizableState:(NSWindow*)window {
|
|
||||||
// origResizable_ = window.styleMask & NSWindowStyleMaskResizable;
|
|
||||||
// if (!origResizable_) {
|
|
||||||
// window.styleMask |= NSWindowStyleMaskResizable;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)popResizableState:(NSWindow*)window {
|
|
||||||
// if (!origResizable_) {
|
|
||||||
// window.styleMask &= ~NSWindowStyleMaskResizable;
|
|
||||||
// }
|
|
||||||
// origResizable_ = false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)windowWillEnterFullScreen:(NSNotification *)notification {
|
|
||||||
// NSWindow* window = (NSWindow*)[notification object];
|
|
||||||
// [self pushResizableState:window];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)windowDidEnterFullScreen:(NSNotification *)notification {
|
|
||||||
// NSWindow* window = (NSWindow*)[notification object];
|
|
||||||
// [self popResizableState:window];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)windowWillExitFullScreen:(NSNotification *)notification {
|
|
||||||
// NSWindow* window = (NSWindow*)[notification object];
|
|
||||||
// [self pushResizableState:window];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// - (void)windowDidExitFullScreen:(NSNotification *)notification {
|
|
||||||
// NSWindow* window = (NSWindow*)[notification object];
|
|
||||||
// [self popResizableState:window];
|
|
||||||
// // Do not call setFrame here (#2295). setFrame here causes unexpected results.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @end
|
|
||||||
//
|
|
||||||
// static void initializeWindow(uintptr_t windowPtr) {
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// // This delegate is never released. This assumes that the window lives until the process lives.
|
|
||||||
// window.delegate = [[EbitengineWindowDelegate alloc] initWithOrigDelegate:window.delegate];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void currentMonitorPos(uintptr_t windowPtr, int* x, int* y) {
|
|
||||||
// @autoreleasepool {
|
|
||||||
// NSScreen* screen = [NSScreen mainScreen];
|
|
||||||
// if (windowPtr) {
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// if ([window isVisible]) {
|
|
||||||
// // When the window is visible, the window is already initialized.
|
|
||||||
// // [NSScreen mainScreen] sometimes tells a lie when the window is put across monitors (#703).
|
|
||||||
// screen = [window screen];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// NSDictionary* screenDictionary = [screen deviceDescription];
|
|
||||||
// NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"];
|
|
||||||
// CGDirectDisplayID aID = [screenID unsignedIntValue];
|
|
||||||
// const CGRect bounds = CGDisplayBounds(aID);
|
|
||||||
// *x = bounds.origin.x;
|
|
||||||
// *y = bounds.origin.y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static bool isNativeFullscreen(uintptr_t windowPtr) {
|
|
||||||
// if (!windowPtr) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// return (window.styleMask & NSWindowStyleMaskFullScreen) != 0;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void setNativeFullscreen(uintptr_t windowPtr, bool fullscreen) {
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// if (((window.styleMask & NSWindowStyleMaskFullScreen) != 0) == fullscreen) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Even though EbitengineWindowDelegate is used, this hack is still required.
|
|
||||||
// // toggleFullscreen doesn't work when the window is not resizable.
|
|
||||||
// bool origFullscreen = window.collectionBehavior & NSWindowCollectionBehaviorFullScreenPrimary;
|
|
||||||
// if (!origFullscreen) {
|
|
||||||
// window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
|
||||||
// }
|
|
||||||
// [window toggleFullScreen:nil];
|
|
||||||
// if (!origFullscreen) {
|
|
||||||
// window.collectionBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void adjustViewSize(uintptr_t windowPtr) {
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// if ((window.styleMask & NSWindowStyleMaskFullScreen) == 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Apparently, adjusting the view size is not needed as of macOS 12 (#1745).
|
|
||||||
// static int majorVersion = 0;
|
|
||||||
// if (majorVersion == 0) {
|
|
||||||
// majorVersion = [[NSProcessInfo processInfo] operatingSystemVersion].majorVersion;
|
|
||||||
// }
|
|
||||||
// if (majorVersion >= 12) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Reduce the view height (#1745).
|
|
||||||
// // https://stackoverflow.com/questions/27758027/sprite-kit-serious-fps-issue-in-full-screen-mode-on-os-x
|
|
||||||
// CGSize windowSize = [window frame].size;
|
|
||||||
// NSView* view = [window contentView];
|
|
||||||
// CGSize viewSize = [view frame].size;
|
|
||||||
// if (windowSize.width != viewSize.width || windowSize.height != viewSize.height) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// viewSize.width--;
|
|
||||||
// [view setFrameSize:viewSize];
|
|
||||||
//
|
|
||||||
// // NSColor.blackColor (0, 0, 0, 1) didn't work.
|
|
||||||
// // Use the transparent color instead.
|
|
||||||
// [window setBackgroundColor: [NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:0]];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void setNativeCursor(int cursorID) {
|
|
||||||
// id cursor = [[NSCursor class] performSelector:@selector(arrowCursor)];
|
|
||||||
// switch (cursorID) {
|
|
||||||
// case 0:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(arrowCursor)];
|
|
||||||
// break;
|
|
||||||
// case 1:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(IBeamCursor)];
|
|
||||||
// break;
|
|
||||||
// case 2:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(crosshairCursor)];
|
|
||||||
// break;
|
|
||||||
// case 3:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(pointingHandCursor)];
|
|
||||||
// break;
|
|
||||||
// case 4:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(_windowResizeEastWestCursor)];
|
|
||||||
// break;
|
|
||||||
// case 5:
|
|
||||||
// cursor = [[NSCursor class] performSelector:@selector(_windowResizeNorthSouthCursor)];
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// [cursor push];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void currentMouseLocation(int* x, int* y) {
|
|
||||||
// NSPoint location = [NSEvent mouseLocation];
|
|
||||||
// *x = (int)(location.x);
|
|
||||||
// *y = (int)(location.y);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void setAllowFullscreen(uintptr_t windowPtr, bool allowFullscreen) {
|
|
||||||
// NSWindow* window = (NSWindow*)windowPtr;
|
|
||||||
// if (allowFullscreen) {
|
|
||||||
// window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
|
||||||
// } else {
|
|
||||||
// window.collectionBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ebitengine/purego/objc"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/glfw"
|
"github.com/hajimehoshi/ebiten/v2/internal/glfw"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var class_EbitengineWindowDelegate objc.Class
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
class_EbitengineWindowDelegate = objc.AllocateClassPair(objc.GetClass("NSObject"), "EbitengineWindowDelegate", 0)
|
||||||
|
protocol := objc.GetProtocol("NSWindowDelegate")
|
||||||
|
class_EbitengineWindowDelegate.AddProtocol(protocol)
|
||||||
|
// TODO: remove these Ivars and place them in Go since there is only ever one instance of this class
|
||||||
|
class_EbitengineWindowDelegate.AddIvar("origDelegate", objc.ID(0), "@")
|
||||||
|
class_EbitengineWindowDelegate.AddIvar("origResizable", false, "B")
|
||||||
|
origDelegateOffset := class_EbitengineWindowDelegate.InstanceVariable("origDelegate").Offset()
|
||||||
|
origResizableOffset := class_EbitengineWindowDelegate.InstanceVariable("origResizable").Offset()
|
||||||
|
getOrigDelegate := func(self objc.ID) objc.ID {
|
||||||
|
selfPtr := *(**uintptr)(unsafe.Pointer(&self))
|
||||||
|
return *(*objc.ID)(unsafe.Pointer(uintptr(unsafe.Pointer(selfPtr)) + origDelegateOffset))
|
||||||
|
}
|
||||||
|
getResizable := func(self objc.ID) bool {
|
||||||
|
selfPtr := *(**uintptr)(unsafe.Pointer(&self))
|
||||||
|
return *(*bool)(unsafe.Pointer(uintptr(unsafe.Pointer(selfPtr)) + origResizableOffset))
|
||||||
|
}
|
||||||
|
setResizable := func(self objc.ID, resizable bool) {
|
||||||
|
selfPtr := *(**uintptr)(unsafe.Pointer(&self))
|
||||||
|
*(*bool)(unsafe.Pointer(uintptr(unsafe.Pointer(selfPtr)) + origResizableOffset)) = resizable
|
||||||
|
}
|
||||||
|
pushResizableState := func(self, w objc.ID) {
|
||||||
|
window := cocoa.NSWindow{ID: w}
|
||||||
|
setResizable(self, window.StyleMask()&cocoa.NSWindowStyleMaskResizable != 0)
|
||||||
|
if !getResizable(self) {
|
||||||
|
window.SetStyleMask(window.StyleMask() | cocoa.NSWindowStyleMaskResizable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popResizableState := func(self, w objc.ID) {
|
||||||
|
window := cocoa.NSWindow{ID: w}
|
||||||
|
if !getResizable(self) {
|
||||||
|
window.SetStyleMask(window.StyleMask() & ^uint(cocoa.NSWindowStyleMaskResizable))
|
||||||
|
}
|
||||||
|
setResizable(self, false)
|
||||||
|
}
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("initWithOrigDelegate:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, origDelegate objc.ID) objc.ID {
|
||||||
|
self = self.SendSuper(objc.RegisterName("init"))
|
||||||
|
if self != 0 {
|
||||||
|
selfPtr := *(**uintptr)(unsafe.Pointer(&self))
|
||||||
|
*(*objc.ID)(unsafe.Pointer(uintptr(unsafe.Pointer(selfPtr)) + origDelegateOffset)) = origDelegate
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}), "@@:B")
|
||||||
|
// The method set of origDelegate_ must sync with GLFWWindowDelegate's implementation.
|
||||||
|
// See cocoa_window.m in GLFW.
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowShouldClose:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) int {
|
||||||
|
return int(getOrigDelegate(self).Send(objc.RegisterName("windowShouldClose:"), notification))
|
||||||
|
}), "B@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidResize:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidMove:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidMiniaturize:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidDeminiaturize:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidBecomeKey:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidResignKey:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidChangeOcclusionState:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
getOrigDelegate(self).Send(cmd, notification)
|
||||||
|
}), "v@:@")
|
||||||
|
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowWillEnterFullScreen:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
pushResizableState(self, cocoa.NSNotification{ID: notification}.Object())
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidEnterFullScreen:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
popResizableState(self, cocoa.NSNotification{ID: notification}.Object())
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowWillExitFullScreen:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
pushResizableState(self, cocoa.NSNotification{ID: notification}.Object())
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.AddMethod(objc.RegisterName("windowDidExitFullScreen:"), objc.NewIMP(func(self objc.ID, cmd objc.SEL, notification objc.ID) {
|
||||||
|
popResizableState(self, cocoa.NSNotification{ID: notification}.Object())
|
||||||
|
// Do not call setFrame here (#2295). setFrame here causes unexpected results.
|
||||||
|
}), "v@:@")
|
||||||
|
class_EbitengineWindowDelegate.Register()
|
||||||
|
}
|
||||||
|
|
||||||
type graphicsDriverCreatorImpl struct {
|
type graphicsDriverCreatorImpl struct {
|
||||||
transparent bool
|
transparent bool
|
||||||
}
|
}
|
||||||
@ -300,10 +183,22 @@ func flipY(y int) int {
|
|||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var class_NSEvent = objc.GetClass("NSEvent")
|
||||||
|
var sel_mouseLocation = objc.RegisterName("mouseLocation")
|
||||||
|
|
||||||
|
func currentMouseLocation() (x, y int) {
|
||||||
|
sig := cocoa.NSMethodSignature_signatureWithObjCTypes("{NSPoint=dd}@:")
|
||||||
|
inv := cocoa.NSInvocation_invocationWithMethodSignature(sig)
|
||||||
|
inv.SetTarget(objc.ID(class_NSEvent))
|
||||||
|
inv.SetSelector(sel_mouseLocation)
|
||||||
|
inv.Invoke()
|
||||||
|
var point cocoa.NSPoint
|
||||||
|
inv.GetReturnValue(unsafe.Pointer(&point))
|
||||||
|
return int(point.X), int(point.Y)
|
||||||
|
}
|
||||||
|
|
||||||
func initialMonitorByOS() (*glfw.Monitor, error) {
|
func initialMonitorByOS() (*glfw.Monitor, error) {
|
||||||
var cx, cy C.int
|
x, y := currentMouseLocation()
|
||||||
C.currentMouseLocation(&cx, &cy)
|
|
||||||
x, y := int(cx), flipY(int(cy))
|
|
||||||
|
|
||||||
// Find the monitor including the cursor.
|
// Find the monitor including the cursor.
|
||||||
for _, m := range ensureMonitors() {
|
for _, m := range ensureMonitors() {
|
||||||
@ -317,10 +212,20 @@ func initialMonitorByOS() (*glfw.Monitor, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func monitorFromWindowByOS(w *glfw.Window) *glfw.Monitor {
|
func monitorFromWindowByOS(w *glfw.Window) *glfw.Monitor {
|
||||||
var x, y C.int
|
window := cocoa.NSWindow{ID: objc.ID(w.GetCocoaWindow())}
|
||||||
C.currentMonitorPos(C.uintptr_t(w.GetCocoaWindow()), &x, &y)
|
pool := cocoa.NSAutoreleasePool_new()
|
||||||
|
screen := cocoa.NSScreen_mainScreen()
|
||||||
|
if window.ID != 0 && window.IsVisibile() {
|
||||||
|
// When the window is visible, the window is already initialized.
|
||||||
|
// [NSScreen mainScreen] sometimes tells a lie when the window is put across monitors (#703).
|
||||||
|
screen = window.Screen()
|
||||||
|
}
|
||||||
|
screenDictionary := screen.DeviceDescription()
|
||||||
|
screenID := cocoa.NSNumber{ID: screenDictionary.ObjectForKey(cocoa.NSString_alloc().InitWithUTF8String("NSScreenNumber").ID)}
|
||||||
|
aID := uintptr(screenID.UnsignedIntValue()) // CGDirectDisplayID
|
||||||
|
pool.Release()
|
||||||
for _, m := range ensureMonitors() {
|
for _, m := range ensureMonitors() {
|
||||||
if int(x) == m.x && int(y) == m.y {
|
if m.m.GetCocoaMonitor() == aID {
|
||||||
return m.m
|
return m.m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,11 +237,29 @@ func (u *userInterfaceImpl) nativeWindow() uintptr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) isNativeFullscreen() bool {
|
func (u *userInterfaceImpl) isNativeFullscreen() bool {
|
||||||
return bool(C.isNativeFullscreen(C.uintptr_t(u.window.GetCocoaWindow())))
|
return cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) setNativeCursor(shape CursorShape) {
|
func (u *userInterfaceImpl) setNativeCursor(shape CursorShape) {
|
||||||
C.setNativeCursor(C.int(shape))
|
class_NSCursor := objc.GetClass("NSCursor")
|
||||||
|
NSCursor := objc.ID(class_NSCursor).Send(objc.RegisterName("class"))
|
||||||
|
sel_performSelector := objc.RegisterName("performSelector:")
|
||||||
|
cursor := NSCursor.Send(sel_performSelector, objc.RegisterName("arrowCursor"))
|
||||||
|
switch shape {
|
||||||
|
case 0:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("arrowCursor"))
|
||||||
|
case 1:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("IBeamCursor"))
|
||||||
|
case 2:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("crosshairCursor"))
|
||||||
|
case 3:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("pointHandCursor"))
|
||||||
|
case 4:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("_windowResizeEastWestCursor"))
|
||||||
|
case 5:
|
||||||
|
cursor = NSCursor.Send(sel_performSelector, objc.RegisterName("_windowResizeNorthSouthCursor"))
|
||||||
|
}
|
||||||
|
cursor.Send(objc.RegisterName("push"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
||||||
@ -345,27 +268,75 @@ func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sel_collectionBehavior = objc.RegisterName("collectionBehavior")
|
||||||
|
var sel_setCollectionBehavior = objc.RegisterName("setCollectionBehavior:")
|
||||||
|
|
||||||
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
|
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
|
||||||
// Toggling fullscreen might ignore events like keyUp. Ensure that events are fired.
|
// Toggling fullscreen might ignore events like keyUp. Ensure that events are fired.
|
||||||
glfw.WaitEventsTimeout(0.1)
|
glfw.WaitEventsTimeout(0.1)
|
||||||
C.setNativeFullscreen(C.uintptr_t(u.window.GetCocoaWindow()), C.bool(fullscreen))
|
window := cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}
|
||||||
|
if window.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0 == fullscreen {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Even though EbitengineWindowDelegate is used, this hack is still required.
|
||||||
|
// toggleFullscreen doesn't work when the window is not resizable.
|
||||||
|
origFullScreen := window.Send(sel_collectionBehavior)&cocoa.NSWindowCollectionBehaviorFullScreenPrimary != 0
|
||||||
|
if !origFullScreen {
|
||||||
|
window.Send(sel_setCollectionBehavior, window.Send(sel_collectionBehavior)|cocoa.NSWindowCollectionBehaviorFullScreenPrimary)
|
||||||
|
}
|
||||||
|
window.Send(objc.RegisterName("toggleFullScreen:"), 0)
|
||||||
|
if !origFullScreen {
|
||||||
|
window.Send(sel_setCollectionBehavior, window.Send(sel_collectionBehavior)&cocoa.NSWindowCollectionBehaviorFullScreenPrimary)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) adjustViewSize() {
|
func (u *userInterfaceImpl) adjustViewSize() {
|
||||||
if u.graphicsDriver.IsGL() {
|
if u.graphicsDriver.IsGL() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
C.adjustViewSize(C.uintptr_t(u.window.GetCocoaWindow()))
|
window := cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}
|
||||||
|
if window.StyleMask()&cocoa.NSWindowStyleMaskFullScreen == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Apparently, adjusting the view size is not needed as of macOS 12 (#1745).
|
||||||
|
if cocoa.NSProcessInfo_processInfo().IsOperatingSystemAtLeastVersion(cocoa.NSOperatingSystemVersion{
|
||||||
|
Major: 12,
|
||||||
|
}) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce the view height (#1745).
|
||||||
|
// https://stackoverflow.com/questions/27758027/sprite-kit-serious-fps-issue-in-full-screen-mode-on-os-x
|
||||||
|
windowSize := window.Frame().Size
|
||||||
|
view := window.ContentView()
|
||||||
|
viewSize := view.Frame().Size
|
||||||
|
if windowSize.Width != viewSize.Width || windowSize.Height != viewSize.Height {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
viewSize.Width--
|
||||||
|
view.SetFrameSize(viewSize)
|
||||||
|
// NSColor.blackColor (0, 0, 0, 1) didn't work.
|
||||||
|
// Use the transparent color instead.
|
||||||
|
window.SetBackgroundColor(cocoa.NSColor_colorWithSRGBRedGreenBlueAlpha(0, 0, 0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) {
|
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) {
|
||||||
allowFullscreen := mode == WindowResizingModeOnlyFullscreenEnabled ||
|
allowFullscreen := mode == WindowResizingModeOnlyFullscreenEnabled ||
|
||||||
mode == WindowResizingModeEnabled
|
mode == WindowResizingModeEnabled
|
||||||
C.setAllowFullscreen(C.uintptr_t(u.window.GetCocoaWindow()), C.bool(allowFullscreen))
|
collectionBehavior := int(objc.ID(u.window.GetCocoaWindow()).Send(sel_collectionBehavior))
|
||||||
|
if allowFullscreen {
|
||||||
|
collectionBehavior |= cocoa.NSWindowCollectionBehaviorFullScreenPrimary
|
||||||
|
} else {
|
||||||
|
collectionBehavior &^= cocoa.NSWindowCollectionBehaviorFullScreenPrimary
|
||||||
|
}
|
||||||
|
objc.ID(u.window.GetCocoaWindow()).Send(objc.RegisterName("setCollectionBehavior:"), collectionBehavior)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initializeWindowAfterCreation(w *glfw.Window) {
|
func initializeWindowAfterCreation(w *glfw.Window) {
|
||||||
// TODO: Register NSWindowWillEnterFullScreenNotification and so on.
|
// TODO: Register NSWindowWillEnterFullScreenNotification and so on.
|
||||||
// Enable resizing temporary before making the window fullscreen.
|
// Enable resizing temporary before making the window fullscreen.
|
||||||
C.initializeWindow(C.uintptr_t(w.GetCocoaWindow()))
|
nswindow := objc.ID(w.GetCocoaWindow())
|
||||||
|
sel_delegate := objc.RegisterName("delegate")
|
||||||
|
delegate := objc.ID(class_EbitengineWindowDelegate).Send(objc.RegisterName("alloc")).Send(objc.RegisterName("initWithOrigDelegate:"), nswindow.Send(sel_delegate))
|
||||||
|
nswindow.Send(objc.RegisterName("setDelegate:"), delegate)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user