/* This file is part of the Pangolin Project. * http://github.com/stevenlovegrove/Pangolin * * Copyright (c) 2011-2018 Steven Lovegrove, Andrey Mnatsakanov * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // Silence all the OSX GL deprecation messages. #define GL_SILENCE_DEPRECATION #include #include #include #include #include #include #include #include #include #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 # define NSFullScreenWindowMask NSWindowStyleMaskFullScreen # define NSTitledWindowMask NSWindowStyleMaskTitled # define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable # define NSResizableWindowMask NSWindowStyleMaskResizable # define NSClosableWindowMask NSWindowStyleMaskClosable #endif // Hack to fix window focus issue // http://www.miscdebris.net/blog/2010/03/30/solution-for-my-mac-os-x-gui-program-doesnt-get-focus-if-its-outside-an-application-bundle/ extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); } inline void FixOsxFocus() { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" ProcessSerialNumber psn; GetCurrentProcess( &psn ); CPSEnableForegroundOperation( &psn ); SetFrontProcess( &psn ); #pragma clang diagnostic pop } namespace pangolin { extern __thread PangolinGl* context; std::unique_ptr CreateOsxWindowAndBind(std::string window_title, int w, int h, const bool is_highres) { OsxWindow* win = new OsxWindow(window_title, w, h, is_highres); return std::unique_ptr(win); } OsxWindow::OsxWindow( const std::string& title, int width, int height, bool USE_RETINA ) { context = this; PangolinGl::is_double_buffered = true; PangolinGl::windowed_size[0] = width; PangolinGl::windowed_size[1] = height; // // These are important I think! // NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // [pool release]; /////////////////////////////////////////////////////////////////////// // Make sure Application is initialised correctly. // This can be run repeatedly. [NSApplication sharedApplication]; PangolinAppDelegate *delegate = [[PangolinAppDelegate alloc] init]; [NSApp setDelegate:delegate]; [NSApp setPresentationOptions:NSFullScreenWindowMask]; [PangolinNSApplication run_pre]; [PangolinNSApplication run_step]; /////////////////////////////////////////////////////////////////////// // Create Window NSRect viewRect = NSMakeRect( 0.0, 0.0, width, height ); _window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:YES]; [_window setTitle:[NSString stringWithUTF8String:title.c_str()]]; [_window setOpaque:YES]; [_window makeKeyAndOrderFront:NSApp]; [_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary]; PangolinWindowDelegate *windelegate = [[PangolinWindowDelegate alloc] init]; [_window setDelegate:windelegate]; /////////////////////////////////////////////////////////////////////// // Setup Menu // NSMenu *mainMenuBar; // NSMenu *appMenu; // NSMenuItem *menuItem; // mainMenuBar = [[NSMenu alloc] init]; // appMenu = [[NSMenu alloc] initWithTitle:@"Pangolin Application"]; // menuItem = [appMenu addItemWithTitle:@"Quit Pangolin Application" action:@selector(terminate:) keyEquivalent:@"q"]; // [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; // menuItem = [[NSMenuItem alloc] init]; // [menuItem setSubmenu:appMenu]; // [mainMenuBar addItem:menuItem]; // //[NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; // [appMenu release]; // [NSApp setMainMenu:mainMenuBar]; /////////////////////////////////////////////////////////////////////// // Create OpenGL View for Window NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 32, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, 0 }; NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; view = [[PangolinNSGLView alloc] initWithFrame:_window.frame pixelFormat:format]; [format release]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if( USE_RETINA && floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) [view setWantsBestResolutionOpenGLSurface:YES]; #endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ [_window setContentView:view]; [PangolinNSApplication run_step]; glewInit(); FixOsxFocus(); } OsxWindow::~OsxWindow() { // Not sure how to deallocate... } void OsxWindow::StartFullScreen() { if(!is_fullscreen) { [_window toggleFullScreen:nil]; is_fullscreen = true; } } void OsxWindow::StopFullScreen() { if(is_fullscreen) { [_window toggleFullScreen:nil]; is_fullscreen = false; } } void OsxWindow::ToggleFullscreen() { [_window toggleFullScreen:nil]; PangolinGl::is_fullscreen = !PangolinGl::is_fullscreen; } void OsxWindow::Move(int x, int y) { [_window setFrame:CGRectMake(x, y, [_window frame].size.width, [_window frame].size.height) display:NO]; } void OsxWindow::Resize(unsigned int w, unsigned int h) { [_window setFrame:CGRectMake([_window frame].origin.x, [_window frame].origin.y, w, h) display:NO]; } void OsxWindow::MakeCurrent() { [[view openGLContext] makeCurrentContext]; context = this; } void OsxWindow::RemoveCurrent() { [NSOpenGLContext clearCurrentContext]; } void OsxWindow::SwapBuffers() { [[view openGLContext] flushBuffer]; // [[view openGLContext] update]; // [view setNeedsDisplay:YES]; } void OsxWindow::ProcessEvents() { [PangolinNSApplication run_step]; } PANGOLIN_REGISTER_FACTORY(OsxWindow) { struct OsxWindowFactory : public FactoryInterface { std::unique_ptr Open(const Uri& uri) override { const std::string window_title = uri.Get("window_title", "window"); const int w = uri.Get("w", 640); const int h = uri.Get("h", 480); const bool is_highres = uri.Get(PARAM_HIGHRES, false); return std::unique_ptr(CreateOsxWindowAndBind(window_title, w, h, is_highres)); } }; auto factory = std::make_shared(); FactoryRegistry::I().RegisterFactory(factory, 10, "cocoa"); FactoryRegistry::I().RegisterFactory(factory, 100, "default"); } }