如何实现Metal C++应用启动时自动进入全屏模式?
Metal C++应用启动时无法进入全屏模式的问题
我基于Apple官方的Metal C++示例开发,希望应用启动后直接进入全屏模式,但每次启动都只以窗口形式打开。
已尝试的操作
- 在应用委托的
applicationDidFinishLaunching方法中调用NS::Window::init时,设置样式掩码为NS::WindowStyleMaskFullScreen,无报错但仍以窗口启动; - 设置样式掩码为
NS::WindowStyleMaskClosable | NS::WindowStyleMaskTitled | NS::WindowStyleMaskFullScreen,结果同上; - 在
NSWindow.hpp中为NS::Window添加toggleFullscreen方法,调用AppKit的NSWindow的toggleFullScreen:,尝试从菜单项及applicationDidFinishLaunching中调用(在makeKeyAndOrderFront之后),无报错但仍为窗口模式,菜单项触发时代码可执行,窗口也声明支持该选择器; - 尝试以窗口指针和
nullptr作为参数调用toggleFullScreen,均无效果; - 在未修改的教程09代码中做类似修改,结果相同:应用启动及触发菜单选项均无法进入全屏;
- 创建XIB/Objective-C的Metal应用对比,发现其使用相同的
toggleFullScreen:选择器,且设置了NS::WindowStyleMaskResizable样式掩码,添加该掩码后我可以手动切换全屏,但仍无法实现启动即全屏。
最小复现代码
#include <cassert> #define NS_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION #define MTK_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #include <Metal/Metal.hpp> #include <AppKit/AppKit.hpp> #include <MetalKit/MetalKit.hpp> #pragma region Declarations { class Renderer { public: Renderer( MTL::Device* pDevice ); ~Renderer(); void draw( MTK::View* pView ); private: MTL::Device* _pDevice; MTL::CommandQueue* _pCommandQueue; }; class MyMTKViewDelegate : public MTK::ViewDelegate { public: MyMTKViewDelegate( MTL::Device* pDevice ); virtual ~MyMTKViewDelegate() override; virtual void drawInMTKView( MTK::View* pView ) override; private: Renderer* _pRenderer; }; class MyAppDelegate : public NS::ApplicationDelegate { public: ~MyAppDelegate(); NS::Menu* createMenuBar(); virtual void applicationWillFinishLaunching( NS::Notification* pNotification ) override; virtual void applicationDidFinishLaunching( NS::Notification* pNotification ) override; virtual bool applicationShouldTerminateAfterLastWindowClosed( NS::Application* pSender ) override; private: NS::Window* _pWindow; MTK::View* _pMtkView; MTL::Device* _pDevice; MyMTKViewDelegate* _pViewDelegate = nullptr; }; #pragma endregion Declarations } int main( int argc, char* argv[] ) { NS::AutoreleasePool* pAutoreleasePool = NS::AutoreleasePool::alloc()->init(); MyAppDelegate del; NS::Application* pSharedApplication = NS::Application::sharedApplication(); pSharedApplication->setDelegate( &del ); pSharedApplication->run(); pAutoreleasePool->release(); return 0; } #pragma mark - AppDelegate #pragma region AppDelegate { MyAppDelegate::~MyAppDelegate() { _pMtkView->release(); _pWindow->release(); _pDevice->release(); delete _pViewDelegate; } NS::Menu* MyAppDelegate::createMenuBar() { // using NS::StringEncoding::UTF8StringEncoding; using NS::UTF8StringEncoding; NS::Menu* pMainMenu = NS::Menu::alloc()->init(); NS::MenuItem* pAppMenuItem = NS::MenuItem::alloc()->init(); NS::Menu* pAppMenu = NS::Menu::alloc()->init( NS::String::string( "Appname", UTF8StringEncoding ) ); NS::String* appName = NS::RunningApplication::currentApplication()->localizedName(); NS::String* quitItemName = NS::String::string( "Quit ", UTF8StringEncoding )->stringByAppendingString( appName ); SEL quitCb = NS::MenuItem::registerActionCallback( "appQuit", [](void*,SEL,const NS::Object* pSender){ auto pApp = NS::Application::sharedApplication(); pApp->terminate( pSender ); } ); NS::MenuItem* pAppQuitItem = pAppMenu->addItem( quitItemName, quitCb, NS::String::string( "q", UTF8StringEncoding ) ); pAppQuitItem->setKeyEquivalentModifierMask( NS::EventModifierFlagCommand ); pAppMenuItem->setSubmenu( pAppMenu ); NS::MenuItem* pWindowMenuItem = NS::MenuItem::alloc()->init(); NS::Menu* pWindowMenu = NS::Menu::alloc()->init( NS::String::string( "Window", UTF8StringEncoding ) ); SEL closeWindowCb = NS::MenuItem::registerActionCallback( "windowClose", [](void*, SEL, const NS::Object*){ auto pApp = NS::Application::sharedApplication(); pApp->windows()->object< NS::Window >(0)->close(); } ); NS::MenuItem* pCloseWindowItem = pWindowMenu->addItem( NS::String::string( "Close Window", UTF8StringEncoding ), closeWindowCb, NS::String::string( "w", UTF8StringEncoding ) ); pCloseWindowItem->setKeyEquivalentModifierMask( NS::EventModifierFlagCommand ); pWindowMenuItem->setSubmenu( pWindowMenu ); pMainMenu->addItem( pAppMenuItem ); pMainMenu->addItem( pWindowMenuItem ); pAppMenuItem->release(); pWindowMenuItem->release(); pAppMenu->release(); pWindowMenu->release(); return pMainMenu->autorelease(); } void MyAppDelegate::applicationWillFinishLaunching( NS::Notification* pNotification ) { NS::Menu* pMenu = createMenuBar(); NS::Application* pApp = reinterpret_cast< NS::Application* >( pNotification->object() ); pApp->setMainMenu( pMenu ); pApp->setActivationPolicy( NS::ActivationPolicy::ActivationPolicyRegular ); } void MyAppDelegate::applicationDidFinishLaunching( NS::Notification* pNotification ) { CGRect frame = (CGRect){ {100.0, 100.0}, {512.0, 512.0} }; _pWindow = NS::Window::alloc()->init( frame, NS::WindowStyleMaskClosable|NS::WindowStyleMaskTitled|NS::WindowStyleMaskFullScreen, NS::BackingStoreBuffered, false ); _pDevice = MTL::CreateSystemDefaultDevice(); _pMtkView = MTK::View::alloc()->init( frame, _pDevice ); _pMtkView->setColorPixelFormat( MTL::PixelFormat::PixelFormatBGRA8Unorm_sRGB ); _pMtkView->setClearColor( MTL::ClearColor::Make( 1.0, 0.0, 0.0, 1.0 ) ); _pViewDelegate = new MyMTKViewDelegate( _pDevice ); _pMtkView->setDelegate( _pViewDelegate ); _pWindow->setContentView( _pMtkView ); _pWindow->setTitle( NS::String::string( "00 - Window", NS::StringEncoding::UTF8StringEncoding ) ); _pWindow->makeKeyAndOrderFront( nullptr ); NS::Application* pApp = reinterpret_cast< NS::Application* >( pNotification->object() ); pApp->activateIgnoringOtherApps( true ); } bool MyAppDelegate::applicationShouldTerminateAfterLastWindowClosed( NS::Application* pSender ) { return true; } #pragma endregion AppDelegate } #pragma mark - ViewDelegate #pragma region ViewDelegate { MyMTKViewDelegate::MyMTKViewDelegate( MTL::Device* pDevice ) : MTK::ViewDelegate() , _pRenderer( new Renderer( pDevice ) ) { } MyMTKViewDelegate::~MyMTKViewDelegate() { delete _pRenderer; } void MyMTKViewDelegate::drawInMTKView( MTK::View* pView ) { _pRenderer->draw( pView ); } #pragma endregion ViewDelegate } #pragma mark - Renderer #pragma region Renderer { Renderer::Renderer( MTL::Device* pDevice ) : _pDevice( pDevice->retain() ) { _pCommandQueue = _pDevice->newCommandQueue(); } Renderer::~Renderer() { _pCommandQueue->release(); _pDevice->release(); } void Renderer::draw( MTK::View* pView ) { NS::AutoreleasePool* pPool = NS::AutoreleasePool::alloc()->init(); MTL::CommandBuffer* pCmd = _pCommandQueue->commandBuffer(); MTL::RenderPassDescriptor* pRpd = pView->currentRenderPassDescriptor(); MTL::RenderCommandEncoder* pEnc = pCmd->renderCommandEncoder( pRpd ); pEnc->endEncoding(); pCmd->presentDrawable( pView->currentDrawable() ); pCmd->commit(); pPool->release(); } #pragma endregion Renderer }
XIB文件相关片段
<window title="Metal2" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g"> <windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/> <windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> </window>
内容的提问来源于stack exchange,提问作者majinnaibu
相关产品推荐
相关产品推荐

