diff options
author | fuzzard <fuzzard@kodi.tv> | 2021-10-29 16:59:03 +1000 |
---|---|---|
committer | fuzzard <fuzzard@kodi.tv> | 2022-04-16 19:07:54 +1000 |
commit | ba9d5b1be195dff3a5bc3bd9fd68742e569d6237 (patch) | |
tree | fa3b012c3924135a53bceb7d9b623b73f8ce4170 | |
parent | 6ba89e19445909a8da54f48f36fc6f2601cfe8ef (diff) |
[OSX] Further improvements to windowing/input
relocate GL based code to own folders
fixups for input handling
rework/tidy of XBMCApplication
19 files changed, 355 insertions, 446 deletions
diff --git a/cmake/treedata/osx/subdirs.txt b/cmake/treedata/osx/subdirs.txt index abc1d9036d..9bee62332f 100644 --- a/cmake/treedata/osx/subdirs.txt +++ b/cmake/treedata/osx/subdirs.txt @@ -17,4 +17,5 @@ xbmc/platform/posix/storage/discs platform/posix/storage/discs xbmc/platform/posix/threads platform/posix/threads xbmc/platform/posix/utils platform/posix/utils xbmc/windowing/osx windowing/osx +xbmc/windowing/osx/OpenGL windowing/osx/OpenGL xbmc/windowing/osx/SDL windowing/osx/SDL diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 8309414741..bde74257ad 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -4242,8 +4242,7 @@ void CApplication::ProcessSlow() { CServiceBroker::GetPowerManager().ProcessEvents(); -#if defined(TARGET_DARWIN_OSX) -#if defined(SDL_FOUND) +#if defined(TARGET_DARWIN_OSX) && defined(SDL_FOUND) // There is an issue on OS X that several system services ask the cursor to become visible // during their startup routines. Given that we can't control this, we hack it in by // forcing the @@ -4252,7 +4251,6 @@ void CApplication::ProcessSlow() Cocoa_HideMouse(); } #endif -#endif // Temporarily pause pausable jobs when viewing video/picture int currentWindow = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); diff --git a/xbmc/platform/darwin/osx/CMakeLists.txt b/xbmc/platform/darwin/osx/CMakeLists.txt index b26f9d1559..125135b610 100644 --- a/xbmc/platform/darwin/osx/CMakeLists.txt +++ b/xbmc/platform/darwin/osx/CMakeLists.txt @@ -12,11 +12,4 @@ set(HEADERS CocoaInterface.h smc.h XBMCHelper.h) -if(NOT SDL_FOUND) - list(APPEND SOURCES OSXGLView.mm - OSXGLWindow.mm) - list(APPEND HEADERS OSXGLView.h - OSXGLWindow.h) -endif() - core_add_library(platform_osx) diff --git a/xbmc/platform/darwin/osx/OSXGLWindow.h b/xbmc/platform/darwin/osx/OSXGLWindow.h deleted file mode 100644 index d993f018da..0000000000 --- a/xbmc/platform/darwin/osx/OSXGLWindow.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2021- Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#import <Cocoa/Cocoa.h> - -@interface OSXGLWindow : NSWindow <NSWindowDelegate> - -@property(atomic) bool resizeState; - -- (id)initWithContentRect:(NSRect)box styleMask:(uint)style; -- (void)dealloc; - -- (BOOL)windowShouldClose:(id)sender; -- (void)windowWillEnterFullScreen:(NSNotification*)pNotification; -- (void)windowDidExitFullScreen:(NSNotification*)pNotification; - -- (void)windowDidChangeScreen:(NSNotification*)notification; -- (void)windowDidExpose:(NSNotification*)aNotification; -- (void)windowDidMove:(NSNotification*)aNotification; -- (void)windowDidMiniaturize:(NSNotification*)aNotification; -- (void)windowDidDeminiaturize:(NSNotification*)aNotification; - -- (void)windowDidBecomeKey:(NSNotification*)aNotification; -- (void)windowDidResignKey:(NSNotification*)aNotification; - -- (void)windowDidResize:(NSNotification*)aNotification; -- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize; -- (void)windowWillStartLiveResize:(NSNotification*)notification; -- (void)windowDidEndLiveResize:(NSNotification*)notification; - -@end diff --git a/xbmc/platform/darwin/osx/PlatformDarwinOSX.cpp b/xbmc/platform/darwin/osx/PlatformDarwinOSX.cpp index 786704c040..a5d9db273e 100644 --- a/xbmc/platform/darwin/osx/PlatformDarwinOSX.cpp +++ b/xbmc/platform/darwin/osx/PlatformDarwinOSX.cpp @@ -9,7 +9,10 @@ #include "PlatformDarwinOSX.h" #include "Util.h" -#include "windowing/osx/WinSystemOSXGL.h" + +#if defined(HAS_GL) +#include "windowing/osx/OpenGL/WinSystemOSXGL.h" +#endif #include "platform/darwin/osx/XBMCHelper.h" #include "platform/darwin/osx/powermanagement/CocoaPowerSyscall.h" @@ -27,7 +30,9 @@ bool CPlatformDarwinOSX::InitStageOne() if (!CPlatformDarwin::InitStageOne()) return false; +#if defined(HAS_GL) CWinSystemOSXGL::Register(); +#endif CCocoaPowerSyscall::Register(); diff --git a/xbmc/platform/darwin/osx/XBMCApplication.mm b/xbmc/platform/darwin/osx/XBMCApplication.mm index a1c27a24f7..bf79f6cf40 100644 --- a/xbmc/platform/darwin/osx/XBMCApplication.mm +++ b/xbmc/platform/darwin/osx/XBMCApplication.mm @@ -21,77 +21,16 @@ #import "platform/darwin/osx/storage/OSXStorageProvider.h" +#import <Foundation/Foundation.h> #import <sys/param.h> /* for MAXPATHLEN */ #import <unistd.h> -// For some reason, Apple removed setAppleMenu from the headers in 10.4, -// but the method still is there and works. To avoid warnings, we declare -// it ourselves here. -@interface NSApplication (Missing_Methods) -- (void)setAppleMenu:(NSMenu*)menu; -@end - -// Portions of CPS.h -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern "C" -{ - extern OSErr CPSGetCurrentProcess(CPSProcessSerNum* psn); - extern OSErr CPSEnableForegroundOperation( - CPSProcessSerNum* psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); - extern OSErr CPSSetFrontProcess(CPSProcessSerNum* psn); -} - static int gArgc; static char** gArgv; static BOOL gCalledAppMainline = FALSE; -static NSString* getApplicationName(void) -{ - NSString* appName = 0; - - // Determine the application name - NSDictionary* dict = (NSDictionary*)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey:@"CFBundleName"]; - - if (![appName length]) - appName = NSProcessInfo.processInfo.processName; - - return appName; -} -static void setupApplicationMenu(void) -{ - // warning: this code is very odd - NSString* appName = getApplicationName(); - NSMenu* appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - // Add menu items - NSString* title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title - action:@selector(orderFrontStandardAboutPanel:) - keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - // Put menu into the menubar - NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [NSApplication.sharedApplication.mainMenu addItem:menuItem]; - - // Tell the application object that this is now the application menu - [NSApplication.sharedApplication setAppleMenu:appleMenu]; -} - // Create a window menu -static void setupWindowMenu(void) +static NSMenu* setupWindowMenu() { NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; @@ -107,42 +46,29 @@ static void setupWindowMenu(void) menuItem = [[NSMenuItem alloc] initWithTitle:@"Float on Top" action:@selector(floatOnTopToggle:) keyEquivalent:@"t"]; - menuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagControl; + menuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand; [windowMenu addItem:menuItem]; // "Minimize" item menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - menuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagControl; + menuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand; [windowMenu addItem:menuItem]; - // Put menu into the menubar - NSMenuItem* windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" - action:nil - keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [NSApplication.sharedApplication.mainMenu addItem:windowMenuItem]; - - // Tell the application object that this is now the window menu - [NSApplication.sharedApplication setWindowsMenu:windowMenu]; + return windowMenu; } // The main class of the application, the application's delegate @implementation XBMCDelegate // Set the working directory to the .app's parent directory +//! @todo Whats this for, is it required? - (void)setupWorkingDirectory { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8*)parentdir, MAXPATHLEN)) - { - assert(chdir(parentdir) == 0); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); + auto parentPath = NSBundle.mainBundle.bundlePath.stringByDeletingLastPathComponent; + NSAssert([NSFileManager.defaultManager changeCurrentDirectoryPath:parentPath], + @"SetupWorkingDirectory Failed to cwd"); } - (void)stopRunLoop @@ -186,7 +112,7 @@ static void setupWindowMenu(void) struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &rlim) == -1) - CLog::Log(LOGDEBUG, "Failed to set core size limit (%s)", strerror(errno)); + CLog::Log(LOGDEBUG, "Failed to set core size limit ({})", strerror(errno)); #endif setlocale(LC_NUMERIC, "C"); @@ -196,13 +122,6 @@ static void setupWindowMenu(void) XBMC_Run(true, appParamParser); -#ifdef _DEBUG - CServiceBroker::GetLogging().SetLogLevel(LOG_LEVEL_DEBUG); -#else - // CServiceBroker::GetLogging().SetLogLevel(LOG_LEVEL_NORMAL); - CServiceBroker::GetLogging().SetLogLevel(LOG_LEVEL_DEBUG); -#endif - std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort(); if (appPort) appPort->SetRenderGUI(false); @@ -217,7 +136,41 @@ static void setupWindowMenu(void) occluded = false; CWinSystemOSX* winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); - winSystem->SetOcclusionState(occluded); + if (winSystem) + winSystem->SetOcclusionState(occluded); +} + +- (void)applicationWillFinishLaunching:(NSNotification*)notification +{ + NSMenu* menubar = [NSMenu new]; + NSMenuItem* menuBarItem = [NSMenuItem new]; + [menubar addItem:menuBarItem]; + [NSApp setMainMenu:menubar]; + + // Main menu + NSMenu* appMenu = [NSMenu new]; + NSMenuItem* quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit" + action:@selector(terminate:) + keyEquivalent:@"q"]; + [appMenu addItem:quitMenuItem]; + [menuBarItem setSubmenu:appMenu]; + + // Window Menu + NSMenuItem* windowMenuItem = [menubar addItemWithTitle:@"" action:nil keyEquivalent:@""]; + NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + [menubar setSubmenu:windowMenu forItem:windowMenuItem]; + NSMenuItem* fullscreenMenuItem = [[NSMenuItem alloc] initWithTitle:@"Full/Windowed Toggle" + action:@selector(fullScreenToggle:) + keyEquivalent:@"f"]; + fullscreenMenuItem.keyEquivalentModifierMask = + NSEventModifierFlagCommand | NSEventModifierFlagControl; + [windowMenu addItem:fullscreenMenuItem]; + [windowMenu addItemWithTitle:@"Float on Top" + action:@selector(floatOnTopToggle:) + keyEquivalent:@"t"]; + [windowMenu addItemWithTitle:@"Minimize" + action:@selector(performMiniaturize:) + keyEquivalent:@"m"]; } // Called after the internal event loop has started running. @@ -247,7 +200,7 @@ static void setupWindowMenu(void) gCalledAppMainline = TRUE; //window.acceptsMouseMovedEvents = TRUE; - + [NSApp activateIgnoringOtherApps:YES]; // kick our mainloop into an extra thread [NSThread detachNewThreadSelector:@selector(mainLoopThread:) toTarget:self withObject:nil]; } @@ -293,6 +246,8 @@ static void setupWindowMenu(void) * * This message is ignored once the app's mainline has been called. */ + +//! @Todo Transition to application: openURLs: - (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename { const char* temparg; @@ -307,11 +262,11 @@ static void setupWindowMenu(void) temparg = [filename UTF8String]; arglen = strlen(temparg) + 1; arg = (char*)malloc(arglen); - if (arg == NULL) + if (arg == nullptr) return FALSE; newargv = (char**)realloc(gArgv, sizeof(char*) * (gArgc + 2)); - if (newargv == NULL) + if (newargv == nullptr) { free(arg); return FALSE; @@ -320,14 +275,13 @@ static void setupWindowMenu(void) strlcpy(arg, temparg, arglen); gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; + gArgv[gArgc] = nullptr; return TRUE; } - (void)deviceDidMountNotification:(NSNotification*)note { - // calling into c++ code, need to use autorelease pools @autoreleasepool { NSString* volumeLabel = [note.userInfo objectForKey:@"NSWorkspaceVolumeLocalizedNameKey"]; @@ -342,7 +296,6 @@ static void setupWindowMenu(void) - (void)deviceDidUnMountNotification:(NSNotification*)note { - // calling into c++ code, need to use autorelease pools @autoreleasepool { NSString* volumeLabel = [note.userInfo objectForKey:@"NSWorkspaceVolumeLocalizedNameKey"]; @@ -383,30 +336,24 @@ static void setupWindowMenu(void) } } +- (NSMenu*)applicationDockMenu:(NSApplication*)sender +{ + return setupWindowMenu(); +} + @end int main(int argc, char* argv[]) { @autoreleasepool { - XBMCDelegate* xbmc_delegate; - - // Block SIGPIPE - // SIGPIPE repeatably kills us, turn it off - { - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGPIPE); - sigprocmask(SIG_BLOCK, &set, NULL); - } - /* Copy the arguments into a global variable */ /* This is passed if we are launched by double-clicking */ if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) { gArgv = (char**)malloc(sizeof(char*) * 2); gArgv[0] = argv[0]; - gArgv[1] = NULL; + gArgv[1] = nullptr; gArgc = 1; } else @@ -420,24 +367,17 @@ int main(int argc, char* argv[]) // Ensure the application object is initialised [NSApplication sharedApplication]; - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN, 0x03, 0x3C, 0x2C, 0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; - - // Set up the menubars - [NSApplication.sharedApplication setMainMenu:[[NSMenu alloc] init]]; - setupApplicationMenu(); - setupWindowMenu(); + // Make sure we call applicationWillTerminate on SIGTERM + [NSProcessInfo.processInfo disableSuddenTermination]; - // Create XBMCDelegate and make it the app delegate - xbmc_delegate = [[XBMCDelegate alloc] init]; - [NSApplication.sharedApplication setDelegate:xbmc_delegate]; + // Set App Delegate + auto appDelegate = [XBMCDelegate new]; + NSApp.delegate = appDelegate; + // Set NSApp to show in dock + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; // Start the main event loop - [NSApplication.sharedApplication run]; + [NSApp run]; return 1; } diff --git a/xbmc/windowing/osx/CMakeLists.txt b/xbmc/windowing/osx/CMakeLists.txt index 20af0813fd..433f5cfe14 100644 --- a/xbmc/windowing/osx/CMakeLists.txt +++ b/xbmc/windowing/osx/CMakeLists.txt @@ -14,9 +14,4 @@ if(NOT SDL_FOUND) WinSystemOSX.h) endif() -if(OPENGL_FOUND) - list(APPEND SOURCES WinSystemOSXGL.mm) - list(APPEND HEADERS WinSystemOSXGL.h) -endif() - core_add_library(windowing_osx) diff --git a/xbmc/windowing/osx/OpenGL/CMakeLists.txt b/xbmc/windowing/osx/OpenGL/CMakeLists.txt new file mode 100644 index 0000000000..fd250d74ef --- /dev/null +++ b/xbmc/windowing/osx/OpenGL/CMakeLists.txt @@ -0,0 +1,14 @@ +if(OPENGL_FOUND) + set(SOURCES WinSystemOSXGL.mm) + set(HEADERS WinSystemOSXGL.h) + + if(NOT SDL_FOUND) + list(APPEND SOURCES OSXGLView.mm + OSXGLWindow.mm) + list(APPEND HEADERS OSXGLView.h + OSXGLWindow.h) + endif() + + core_add_library(windowing_osx_opengl) + +endif() diff --git a/xbmc/platform/darwin/osx/OSXGLView.h b/xbmc/windowing/osx/OpenGL/OSXGLView.h index 7849cea24d..577642dc5e 100644 --- a/xbmc/platform/darwin/osx/OSXGLView.h +++ b/xbmc/windowing/osx/OpenGL/OSXGLView.h @@ -11,17 +11,8 @@ #import <Cocoa/Cocoa.h> @interface OSXGLView : NSOpenGLView -{ - NSOpenGLContext* m_glcontext; - NSOpenGLPixelFormat* m_pixFmt; - NSTrackingArea* m_trackingArea; - BOOL pause; -} - -@property(readonly, getter=getCurrentNSContext) NSOpenGLContext* context; - (id)initWithFrame:(NSRect)frameRect; -- (void)dealloc; - (NSOpenGLContext*)getGLContext; @end diff --git a/xbmc/platform/darwin/osx/OSXGLView.mm b/xbmc/windowing/osx/OpenGL/OSXGLView.mm index c7fa7b67c8..eb899ac5b9 100644 --- a/xbmc/platform/darwin/osx/OSXGLView.mm +++ b/xbmc/windowing/osx/OpenGL/OSXGLView.mm @@ -20,6 +20,12 @@ #include "system_gl.h" @implementation OSXGLView +{ + NSOpenGLContext* m_glcontext; + NSOpenGLPixelFormat* m_pixFmt; + NSTrackingArea* m_trackingArea; + BOOL pause; +} - (id)initWithFrame:(NSRect)frameRect { @@ -55,11 +61,9 @@ - (void)drawRect:(NSRect)rect { - static BOOL firstRender = YES; - if (firstRender) - { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ [m_glcontext setView:self]; - firstRender = NO; // clear screen on first render glClearColor(0, 0, 0, 0); @@ -67,7 +71,7 @@ glClearColor(0, 0, 0, 0); [m_glcontext update]; - } + }); } - (void)updateTrackingAreas diff --git a/xbmc/windowing/osx/OpenGL/OSXGLWindow.h b/xbmc/windowing/osx/OpenGL/OSXGLWindow.h new file mode 100644 index 0000000000..a722804c8d --- /dev/null +++ b/xbmc/windowing/osx/OpenGL/OSXGLWindow.h @@ -0,0 +1,19 @@ +#pragma once + +/* + * Copyright (C) 2021- Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#import <Cocoa/Cocoa.h> + +@interface OSXGLWindow : NSWindow <NSWindowDelegate> + +@property(atomic) bool resizeState; + +- (id)initWithContentRect:(NSRect)box styleMask:(uint)style; + +@end diff --git a/xbmc/platform/darwin/osx/OSXGLWindow.mm b/xbmc/windowing/osx/OpenGL/OSXGLWindow.mm index a550301259..366d0674e2 100644 --- a/xbmc/platform/darwin/osx/OSXGLWindow.mm +++ b/xbmc/windowing/osx/OpenGL/OSXGLWindow.mm @@ -18,11 +18,11 @@ #include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" +#import "windowing/osx/OpenGL/OSXGLView.h" #include "windowing/osx/WinEventsOSX.h" #import "windowing/osx/WinSystemOSX.h" #include "platform/darwin/osx/CocoaInterface.h" -#import "platform/darwin/osx/OSXGLView.h" //------------------------------------------------------------------------------------------ @implementation OSXGLWindow @@ -52,7 +52,7 @@ - (BOOL)windowShouldClose:(id)sender { if (!g_application.m_bStop) - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_QUIT); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_QUIT); return NO; } @@ -96,20 +96,20 @@ if (!m_resizeState) { NSRect rect = [self contentRectForFrameRect:self.frame]; + int width = static_cast<int>(rect.size.width); + int height = static_cast<int>(rect.size.height); if (!CServiceBroker::GetWinSystem()->IsFullScreen()) { RESOLUTION res_index = RES_DESKTOP; - if ((static_cast<int>(rect.size.width) == - CDisplaySettings::GetInstance().GetResolutionInfo(res_index).iWidth) && - (static_cast<int>(rect.size.height) == - CDisplaySettings::GetInstance().GetResolutionInfo(res_index).iHeight)) + if ((width == CDisplaySettings::GetInstance().GetResolutionInfo(res_index).iWidth) && + (height == CDisplaySettings::GetInstance().GetResolutionInfo(res_index).iHeight)) return; } XBMC_Event newEvent = {}; newEvent.type = XBMC_VIDEORESIZE; - newEvent.resize.w = static_cast<int>(rect.size.width); - newEvent.resize.h = static_cast<int>(rect.size.height); + newEvent.resize.w = width; + newEvent.resize.h = height; // check for valid sizes cause in some cases // we are hit during fullscreen transition from osx @@ -140,6 +140,9 @@ - (void)windowWillEnterFullScreen:(NSNotification*)pNotification { CWinSystemOSX* winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); + if (!winSystem) + return; + // if osx is the issuer of the toggle // call XBMCs toggle function if (!winSystem->GetFullscreenWillToggle()) @@ -149,7 +152,7 @@ // called from XBMCs gui thread winSystem->SetFullscreenWillToggle(true); - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_TOGGLEFULLSCREEN); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_TOGGLEFULLSCREEN); } else { @@ -163,6 +166,9 @@ - (void)windowDidExitFullScreen:(NSNotification*)pNotification { auto winSystem = dynamic_cast<CWinSystemOSX*>(CServiceBroker::GetWinSystem()); + if (!winSystem) + return; + // if osx is the issuer of the toggle // call XBMCs toggle function if (!winSystem->GetFullscreenWillToggle()) @@ -171,7 +177,7 @@ // flag will be reset in SetFullscreen once its // called from XBMCs gui thread winSystem->SetFullscreenWillToggle(true); - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_TOGGLEFULLSCREEN); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_TOGGLEFULLSCREEN); } else { @@ -182,6 +188,17 @@ } } +- (NSApplicationPresentationOptions)window:(NSWindow*)window + willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions +{ + // customize our appearance when entering full screen: + // we don't want the dock to appear but we want the menubar to hide/show automatically + // + return (NSApplicationPresentationFullScreen | // support full screen for this window (required) + NSApplicationPresentationHideDock | // completely hide the dock + NSApplicationPresentationAutoHideMenuBar); // yes we want the menu bar to show/hide +} + - (void)windowDidMiniaturize:(NSNotification*)aNotification { g_application.m_AppFocused = false; diff --git a/xbmc/windowing/osx/WinSystemOSXGL.h b/xbmc/windowing/osx/OpenGL/WinSystemOSXGL.h index 750d2ad9c7..c38e5e3491 100644 --- a/xbmc/windowing/osx/WinSystemOSXGL.h +++ b/xbmc/windowing/osx/OpenGL/WinSystemOSXGL.h @@ -11,7 +11,7 @@ #if defined(HAS_SDL) #include "windowing/osx/SDL/WinSystemOSXSDL.h" #else -#include "WinSystemOSX.h" +#include "windowing/osx/WinSystemOSX.h" #endif #include "rendering/gl/RenderSystemGL.h" diff --git a/xbmc/windowing/osx/WinSystemOSXGL.mm b/xbmc/windowing/osx/OpenGL/WinSystemOSXGL.mm index 30e44f2b34..30e44f2b34 100644 --- a/xbmc/windowing/osx/WinSystemOSXGL.mm +++ b/xbmc/windowing/osx/OpenGL/WinSystemOSXGL.mm diff --git a/xbmc/windowing/osx/WinEventsOSX.mm b/xbmc/windowing/osx/WinEventsOSX.mm index ac04bb8333..b2d07db936 100644 --- a/xbmc/windowing/osx/WinEventsOSX.mm +++ b/xbmc/windowing/osx/WinEventsOSX.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2018 Team Kodi + * Copyright (C) 2011-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later diff --git a/xbmc/windowing/osx/WinEventsOSXImpl.h b/xbmc/windowing/osx/WinEventsOSXImpl.h index 8e732bd7a3..2dcacd44f0 100644 --- a/xbmc/windowing/osx/WinEventsOSXImpl.h +++ b/xbmc/windowing/osx/WinEventsOSXImpl.h @@ -10,15 +10,16 @@ #include "windowing/osx/WinEventsOSX.h" +#import <CoreGraphics/CoreGraphics.h> #import <Foundation/Foundation.h> @interface CWinEventsOSXImpl : NSObject -- (instancetype)init; - (void)MessagePush:(XBMC_Event*)newEvent; - (size_t)GetQueueSize; - (bool)MessagePump; - (void)enableInputEvents; - (void)disableInputEvents; +- (XBMC_Event)keyPressEvent:(CGEventRef*)event; @end diff --git a/xbmc/windowing/osx/WinEventsOSXImpl.mm b/xbmc/windowing/osx/WinEventsOSXImpl.mm index 7edeef46d6..950777ea4c 100644 --- a/xbmc/windowing/osx/WinEventsOSXImpl.mm +++ b/xbmc/windowing/osx/WinEventsOSXImpl.mm @@ -17,13 +17,15 @@ #include "input/mouse/MouseStat.h" #include "messaging/ApplicationMessenger.h" #include "threads/CriticalSection.h" -#include "threads/SingleLock.h" +#include "utils/log.h" #include "windowing/osx/WinSystemOSX.h" -#include <list> #include <memory> +#include <mutex> +#include <queue> #import <AppKit/AppKit.h> +#import <Carbon/Carbon.h> // kvk_ANSI_ keycodes #import <CoreGraphics/CoreGraphics.h> #import <Foundation/Foundation.h> @@ -31,8 +33,8 @@ @implementation CWinEventsOSXImpl { - std::list<XBMC_Event> events; - CCriticalSection g_inputCond; + std::queue<XBMC_Event> events; + CCriticalSection m_inputlock; id mLocalMonitorId; } @@ -49,8 +51,8 @@ - (void)MessagePush:(XBMC_Event*)newEvent { - CSingleLock lock(g_inputCond); - events.push_back(*newEvent); + std::unique_lock<CCriticalSection> lock(m_inputlock); + events.emplace(*newEvent); } - (bool)MessagePump @@ -66,11 +68,11 @@ // deeper message loop and call the deeper MessagePump from there. XBMC_Event pumpEvent = {}; { - CSingleLock lock(g_inputCond); + std::unique_lock<CCriticalSection> lock(m_inputlock); if (events.size() == 0) return ret; pumpEvent = events.front(); - events.pop_front(); + events.pop(); } std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort(); if (appPort) @@ -81,7 +83,7 @@ - (size_t)GetQueueSize { - CSingleLock lock(g_inputCond); + std::unique_lock<CCriticalSection> lock(m_inputlock); return events.size(); } @@ -89,19 +91,19 @@ { switch (character) { - case 0x1c: - case 0xf702: + case kVK_ANSI_8: + case NSLeftArrowFunctionKey: return XBMCK_LEFT; - case 0x1d: - case 0xf703: + case kVK_ANSI_0: + case NSRightArrowFunctionKey: return XBMCK_RIGHT; - case 0x1e: - case 0xf700: + case kVK_ANSI_RightBracket: + case NSUpArrowFunctionKey: return XBMCK_UP; - case 0x1f: - case 0xf701: + case kVK_ANSI_O: + case NSDownArrowFunctionKey: return XBMCK_DOWN; - case 0x7f: + case NSDeleteCharacter: return XBMCK_BACKSPACE; default: return character; @@ -127,35 +129,35 @@ if (appleModifier & kCGEventFlagMaskCommand) xbmcModifier |= XBMCKMOD_LMETA; - return (XBMCMod)xbmcModifier; + return static_cast<XBMCMod>(xbmcModifier); } - (bool)ProcessOSXShortcuts:(XBMC_Event&)event { - bool cmd = !!(event.key.keysym.mod & (XBMCKMOD_LMETA | XBMCKMOD_RMETA)); + const auto cmd = (event.key.keysym.mod & (XBMCKMOD_LMETA | XBMCKMOD_RMETA)) != 0; if (cmd && event.type == XBMC_KEYDOWN) { switch (event.key.keysym.sym) { case XBMCK_q: // CMD-q to quit if (!g_application.m_bStop) - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_QUIT); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_QUIT); return true; - case XBMCK_CTRLF: // CMD-f to toggle fullscreen - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_TOGGLEFULLSCREEN); + case XBMCK_CTRLF: // CMD-CTRL-f to toggle fullscreen + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_TOGGLEFULLSCREEN); return true; case XBMCK_s: // CMD-s to take a screenshot { CAction* action = new CAction(ACTION_TAKE_SCREENSHOT); - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg( - TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast<void*>(action)); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, + static_cast<void*>(action)); return true; } case XBMCK_h: // CMD-h to hide (but we minimize for now) case XBMCK_m: // CMD-m to minimize - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_MINIMIZE); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_MINIMIZE); return true; default: @@ -170,12 +172,19 @@ { [self disableInputEvents]; // allow only one registration at a time + // clang-format off // Create an event tap. We are interested in mouse and keyboard events. NSEventMask eventMask = - NSEventMaskLeftMouseDown | NSEventMaskLeftMouseUp | NSEventMaskRightMouseDown | - NSEventMaskRightMouseUp | NSEventMaskLeftMouseDragged | NSEventMaskRightMouseDragged | - NSEventMaskOtherMouseDown | NSEventMaskOtherMouseUp | NSEventMaskOtherMouseDragged | - NSEventMaskMouseMoved | NSEventMaskScrollWheel | NSEventMaskKeyDown | NSEventMaskKeyUp; + NSEventMaskKeyDown | NSEventMaskKeyUp | + NSEventMaskLeftMouseDown | NSEventMaskLeftMouseUp | + NSEventMaskRightMouseDown | NSEventMaskRightMouseUp | + NSEventMaskOtherMouseDown | NSEventMaskOtherMouseUp | + NSEventMaskScrollWheel | + NSEventMaskLeftMouseDragged | + NSEventMaskRightMouseDragged | + NSEventMaskOtherMouseDragged | + NSEventMaskMouseMoved; + // clang-format on mLocalMonitorId = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent* event) { @@ -187,7 +196,7 @@ { // Disable the local Monitor if (mLocalMonitorId != nil) - [NSEvent removeMonitor:(id)mLocalMonitorId]; + [NSEvent removeMonitor:mLocalMonitorId]; mLocalMonitorId = nil; } @@ -210,9 +219,6 @@ NSRect frame = winSystem->GetWindowDimensions(); location.y = frame.size.height - location.y; - UniChar unicodeString[10]; - UniCharCount actualStringLength = 10; - CGKeyCode keycode; XBMC_Event newEvent = {}; switch (type) @@ -290,40 +296,15 @@ // handle keyboard events and transform them into the xbmc event world case kCGEventKeyUp: - keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); - CGEventKeyboardGetUnicodeString(event, sizeof(unicodeString) / sizeof(*unicodeString), - &actualStringLength, unicodeString); - if (actualStringLength > 0) - unicodeString[0] = [self OsxKey2XbmcKey:unicodeString[0]]; - else - unicodeString[0] = [self OsxKey2XbmcKey:[nsevent.characters characterAtIndex:0]]; - + newEvent = [self keyPressEvent:&event]; newEvent.type = XBMC_KEYUP; - newEvent.key.keysym.scancode = keycode; - newEvent.key.keysym.sym = (XBMCKey)unicodeString[0]; - newEvent.key.keysym.unicode = unicodeString[0]; - if (actualStringLength > 1) - newEvent.key.keysym.unicode |= (unicodeString[1] << 8); - newEvent.key.keysym.mod = [self OsxMod2XbmcMod:CGEventGetFlags(event)]; + [self MessagePush:&newEvent]; passEvent = false; break; case kCGEventKeyDown: - keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); - CGEventKeyboardGetUnicodeString(event, sizeof(unicodeString) / sizeof(*unicodeString), - &actualStringLength, unicodeString); - if (actualStringLength > 0) - unicodeString[0] = [self OsxKey2XbmcKey:unicodeString[0]]; - else - unicodeString[0] = [self OsxKey2XbmcKey:[nsevent.characters characterAtIndex:0]]; - + newEvent = [self keyPressEvent:&event]; newEvent.type = XBMC_KEYDOWN; - newEvent.key.keysym.scancode = keycode; - newEvent.key.keysym.sym = (XBMCKey)unicodeString[0]; - newEvent.key.keysym.unicode = unicodeString[0]; - if (actualStringLength > 1) - newEvent.key.keysym.unicode |= (unicodeString[1] << 8); - newEvent.key.keysym.mod = [self OsxMod2XbmcMod:CGEventGetFlags(event)]; if (![self ProcessOSXShortcuts:newEvent]) [self MessagePush:&newEvent]; @@ -340,4 +321,44 @@ return nullptr; } +- (XBMC_Event)keyPressEvent:(CGEventRef*)event +{ + UniCharCount actualStringLength = 0; + // Get stringlength of event + CGEventKeyboardGetUnicodeString(*event, 0, &actualStringLength, nullptr); + + // Create array with size of event string + UniChar unicodeString[actualStringLength]; + memset(unicodeString, 0, sizeof(unicodeString)); + + auto keycode = + static_cast<CGKeyCode>(CGEventGetIntegerValueField(*event, kCGKeyboardEventKeycode)); + CGEventKeyboardGetUnicodeString(*event, sizeof(unicodeString) / sizeof(*unicodeString), + &actualStringLength, unicodeString); + + XBMC_Event newEvent = {}; + + // May be possible for actualStringLength > 1. Havent been able to replicate anything + // larger than 1, but keep in mind for any regressions + if (actualStringLength == 0) + { + return newEvent; + } + else if (actualStringLength > 1) + { + CLog::Log(LOGERROR, "CWinEventsOSXImpl::keyPressEvent - event string > 1 - size: {}", + static_cast<int>(actualStringLength)); + return newEvent; + } + + unicodeString[0] = [self OsxKey2XbmcKey:unicodeString[0]]; + + newEvent.key.keysym.scancode = keycode; + newEvent.key.keysym.sym = static_cast<XBMCKey>(unicodeString[0]); + newEvent.key.keysym.unicode = unicodeString[0]; + newEvent.key.keysym.mod = [self OsxMod2XbmcMod:CGEventGetFlags(*event)]; + + return newEvent; +} + @end diff --git a/xbmc/windowing/osx/WinSystemOSX.h b/xbmc/windowing/osx/WinSystemOSX.h index d527b7b60f..0ac08d4d38 100644 --- a/xbmc/windowing/osx/WinSystemOSX.h +++ b/xbmc/windowing/osx/WinSystemOSX.h @@ -26,8 +26,8 @@ class CWinEventsOSX; @class NSWindow; @class OSXGLView; #else -class NSWindow; -class OSXGLView; +struct NSWindow; +struct OSXGLView; #endif class CWinSystemOSX : public CWinSystemBase, public ITimerCallback @@ -95,8 +95,8 @@ protected: void EnableVSync(bool enable); bool SwitchToVideoMode(int width, int height, double refreshrate); void FillInVideoModes(); - bool FlushBuffer(void); - bool IsObscured(void); + bool FlushBuffer(); + bool IsObscured(); bool DestroyWindowInternal(); @@ -114,7 +114,7 @@ protected: std::vector<IDispResource*> m_resources; CTimer m_lostDeviceTimer; bool m_delayDispReset; - XbmcThreads::EndTime m_dispResetTimer; + XbmcThreads::EndTime<> m_dispResetTimer; bool m_fullscreenWillToggle; CCriticalSection m_critSection; }; diff --git a/xbmc/windowing/osx/WinSystemOSX.mm b/xbmc/windowing/osx/WinSystemOSX.mm index 5ab150aafc..492aeada6c 100644 --- a/xbmc/windowing/osx/WinSystemOSX.mm +++ b/xbmc/windowing/osx/WinSystemOSX.mm @@ -27,23 +27,24 @@ #include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "threads/SingleLock.h" +#include "threads/CriticalSection.h" #include "utils/StringUtils.h" #include "utils/log.h" #include "windowing/osx/CocoaDPMSSupport.h" #include "windowing/osx/OSScreenSaverOSX.h" +#import "windowing/osx/OpenGL/OSXGLView.h" +#import "windowing/osx/OpenGL/OSXGLWindow.h" #include "windowing/osx/VideoSyncOsx.h" #include "windowing/osx/WinEventsOSX.h" #include "platform/darwin/DarwinUtils.h" #include "platform/darwin/DictionaryUtils.h" #include "platform/darwin/osx/CocoaInterface.h" -#import "platform/darwin/osx/OSXGLView.h" -#import "platform/darwin/osx/OSXGLWindow.h" #include "platform/darwin/osx/powermanagement/CocoaPowerSyscall.h" #include <chrono> #include <cstdlib> +#include <mutex> #include <signal.h> #import <Cocoa/Cocoa.h> @@ -55,39 +56,22 @@ using namespace KODI; using namespace MESSAGING; using namespace WINDOWING; +using namespace std::chrono_literals; #define MAX_DISPLAYS 32 static NSWindow* blankingWindows[MAX_DISPLAYS]; -//--------------------------------------------------------------------------------- -void SetMenuBarVisible(bool visible) -{ - if (visible) - { - dispatch_sync(dispatch_get_main_queue(), ^{ - NSApplicationPresentationOptions options = NSApplicationPresentationDefault; - [NSApplication.sharedApplication setPresentationOptions:options]; - }); - } - else - { - dispatch_sync(dispatch_get_main_queue(), ^{ - NSApplicationPresentationOptions options = - NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock; - [NSApplication.sharedApplication setPresentationOptions:options]; - }); - } -} - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -// No replacement for CGDisplayModeCopyPixelEncoding -// Disable warning for now size_t DisplayBitsPerPixelForMode(CGDisplayModeRef mode) { size_t bitsPerPixel = 0; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + // No replacement for CGDisplayModeCopyPixelEncoding + // Disable warning for now CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); +#pragma GCC diagnostic pop + if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { @@ -108,22 +92,25 @@ size_t DisplayBitsPerPixelForMode(CGDisplayModeRef mode) return bitsPerPixel; } -#pragma GCC diagnostic pop #pragma mark - GetScreenName -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -// No real replacement of CGDisplayIOServicePort -// Stackoverflow links to https://github.com/glfw/glfw/pull/192 as a possible replacement -// disable warning for now NSString* screenNameForDisplay(CGDirectDisplayID displayID) { NSString* screenName; @autoreleasepool { + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + // No real replacement of CGDisplayIOServicePort + // Stackoverflow links to https://github.com/glfw/glfw/pull/192 as a possible replacement + // disable warning for now NSDictionary* deviceInfo = (__bridge_transfer NSDictionary*)IODisplayCreateInfoDictionary( CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName); + +#pragma GCC diagnostic pop + NSDictionary* localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]]; @@ -145,18 +132,17 @@ NSString* screenNameForDisplay(CGDirectDisplayID displayID) return screenName; } -#pragma GCC diagnostic pop #pragma mark - GetDisplay CGDirectDisplayID GetDisplayID(int screen_index) { CGDirectDisplayID displayArray[MAX_DISPLAYS]; - CGDisplayCount numDisplays; + uint32_t numDisplays; // Get the list of displays. CGGetActiveDisplayList(MAX_DISPLAYS, displayArray, &numDisplays); - if (screen_index >= 0 && screen_index < numDisplays) + if (screen_index >= 0 && screen_index < static_cast<int>(numDisplays)) return (displayArray[screen_index]); else return (displayArray[0]); @@ -215,18 +201,18 @@ CFArrayRef GetAllDisplayModes(CGDirectDisplayID display) if (!number) { CLog::Log(LOGERROR, "GetAllDisplayModes - could not create Number!"); - return NULL; + return nullptr; } CFStringRef key = kCGDisplayShowDuplicateLowResolutionModes; CFDictionaryRef options = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&key, - (const void**)&number, 1, NULL, NULL); + (const void**)&number, 1, nullptr, nullptr); CFRelease(number); if (!options) { CLog::Log(LOGERROR, "GetAllDisplayModes - could not create Dictionary!"); - return NULL; + return nullptr; } CFArrayRef displayModes = CGDisplayCopyAllDisplayModes(display, options); @@ -235,7 +221,7 @@ CFArrayRef GetAllDisplayModes(CGDirectDisplayID display) if (!displayModes) { CLog::Log(LOGERROR, "GetAllDisplayModes - no displaymodes found!"); - return NULL; + return nullptr; } return displayModes; @@ -246,33 +232,31 @@ CFArrayRef GetAllDisplayModes(CGDirectDisplayID display) CGDisplayModeRef GetMode(int width, int height, double refreshrate, int screenIdx) { if (screenIdx >= (signed)[[NSScreen screens] count]) - return NULL; + return nullptr; bool stretched; bool interlaced; bool safeForHardware; - bool televisionoutput; int w, h, bitsperpixel; double rate; RESOLUTION_INFO res; - CLog::Log(LOGDEBUG, "GetMode looking for suitable mode with %d x %d @ %f Hz on display %d", width, + CLog::Log(LOGDEBUG, "GetMode looking for suitable mode with {} x {} @ {} Hz on display {}", width, height, refreshrate, screenIdx); - CFArrayRef displayModes = GetAllDisplayModes(GetDisplayID(screenIdx)); + CFArrayRef allModes = GetAllDisplayModes(GetDisplayID(screenIdx)); - if (!displayModes) - return NULL; + if (!allModes) + return nullptr; - for (int i = 0; i < CFArrayGetCount(displayModes); ++i) + for (int i = 0; i < CFArrayGetCount(allModes); ++i) { - CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, i); + CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); uint32_t flags = CGDisplayModeGetIOFlags(displayMode); - stretched = flags & kDisplayModeStretchedFlag ? true : false; - interlaced = flags & kDisplayModeInterlacedFlag ? true : false; + stretched = (flags & kDisplayModeStretchedFlag) != 0; + interlaced = (flags & kDisplayModeInterlacedFlag) != 0; bitsperpixel = DisplayBitsPerPixelForMode(displayMode); - safeForHardware = flags & kDisplayModeSafetyFlags ? true : false; - televisionoutput = flags & kDisplayModeTelevisionFlag ? true : false; + safeForHardware = (flags & kDisplayModeSafetyFlags) != 0; w = CGDisplayModeGetWidth(displayMode); h = CGDisplayModeGetHeight(displayMode); rate = CGDisplayModeGetRefreshRate(displayMode); @@ -281,24 +265,23 @@ CGDisplayModeRef GetMode(int width, int height, double refreshrate, int screenId (interlaced == false) && (w == width) && (h == height) && (rate == refreshrate || rate == 0)) { + CFRelease(allModes); CLog::Log(LOGDEBUG, "GetMode found a match!"); - return displayMode; + return CGDisplayModeRetain(displayMode); } } - CFRelease(displayModes); + CFRelease(allModes); CLog::Log(LOGERROR, "GetMode - no match found!"); - return NULL; + return nullptr; } // mimic former behavior of deprecated CGDisplayBestModeForParameters -CGDisplayModeRef BestMatchForMode( - CGDirectDisplayID display, size_t bitsPerPixel, size_t width, size_t height, boolean_t& match) +CGDisplayModeRef BestMatchForMode(CGDirectDisplayID display, + size_t bitsPerPixel, + size_t width, + size_t height) { - - // Get a copy of the current display mode - CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(display); - // Loop through all display modes to determine the closest match. // CGDisplayBestModeForParameters is deprecated on 10.6 so we will emulate it's behavior // Try to find a mode with the requested depth and equal or greater dimensions first. @@ -306,35 +289,44 @@ CGDisplayModeRef BestMatchForMode( // If still no match is found, just use the current mode. CFArrayRef allModes = GetAllDisplayModes(display); + if (!allModes) + return nullptr; + + CGDisplayModeRef displayMode = nullptr; + for (int i = 0; i < CFArrayGetCount(allModes); i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); + if (!mode) + continue; + if (DisplayBitsPerPixelForMode(mode) != bitsPerPixel) continue; if ((CGDisplayModeGetWidth(mode) == width) && (CGDisplayModeGetHeight(mode) == height)) { - CGDisplayModeRelease(displayMode); // release the copy we got before ... displayMode = mode; - match = true; break; } } // No depth match was found - if (!match) + if (!displayMode) { for (int i = 0; i < CFArrayGetCount(allModes); i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); + + if (!mode) + continue; + if (DisplayBitsPerPixelForMode(mode) >= bitsPerPixel) continue; if ((CGDisplayModeGetWidth(mode) == width) && (CGDisplayModeGetHeight(mode) == height)) { displayMode = mode; - match = true; break; } } @@ -384,10 +376,7 @@ void BlankOtherDisplays(int screen_index) void UnblankDisplays(void) { - int numDisplays = NSScreen.screens.count; - int i = 0; - - for (i = 0; i < numDisplays; i++) + for (auto i = 0; i < static_cast<int>(NSScreen.screens.count); i++) { if (blankingWindows[i] != 0) { @@ -399,7 +388,7 @@ void UnblankDisplays(void) } #pragma mark - Fade Display - +//! @Todo Look to replace Fade with CABasicAnimation static NSWindow* curtainWindow; void fadeInDisplay(NSScreen* theScreen, double fadeTime) { @@ -462,7 +451,7 @@ static void DisplayReconfigured(CGDirectDisplayID display, if (!winsys) return; - CLog::Log(LOGDEBUG, "CWinSystemOSX::DisplayReconfigured with flags %d", flags); + CLog::Log(LOGDEBUG, "CWinSystemOSX::DisplayReconfigured with flags {}", flags); // we fire the callbacks on start of configuration // or when the mode set was finished @@ -537,13 +526,13 @@ CWinSystemOSX::~CWinSystemOSX() = default; void CWinSystemOSX::Register(IDispResource* resource) { - CSingleLock lock(m_resourceSection); + std::unique_lock<CCriticalSection> lock(m_resourceSection); m_resources.push_back(resource); } void CWinSystemOSX::Unregister(IDispResource* resource) { - CSingleLock lock(m_resourceSection); + std::unique_lock<CCriticalSection> lock(m_resourceSection); std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource); if (i != m_resources.end()) m_resources.erase(i); @@ -551,22 +540,23 @@ void CWinSystemOSX::Unregister(IDispResource* resource) void CWinSystemOSX::AnnounceOnLostDevice() { - CSingleLock lock(m_resourceSection); + std::unique_lock<CCriticalSection> lock(m_resourceSection); // tell any shared resources - CLog::Log(LOGDEBUG, "CWinSystemOSX::AnnounceOnLostDevice"); + CLog::LogF(LOGDEBUG, "Lost Device Announce"); for (std::vector<IDispResource*>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) (*i)->OnLostDisplay(); } void CWinSystemOSX::HandleOnResetDevice() { - - int delay = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( - "videoscreen.delayrefreshchange"); - if (delay > 0) + auto delay = + std::chrono::milliseconds(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( + "videoscreen.delayrefreshchange") * + 100); + if (delay > 0ms) { m_delayDispReset = true; - m_dispResetTimer.Set(delay * 100); + m_dispResetTimer.Set(delay); } else { @@ -586,9 +576,9 @@ void CWinSystemOSX::AnnounceOnResetDevice() CServiceBroker::GetWinSystem()->GetGfxContext().SetFPS(currentFps); - CSingleLock lock(m_resourceSection); + std::unique_lock<CCriticalSection> lock(m_resourceSection); // tell any shared resources - CLog::Log(LOGDEBUG, "CWinSystemOSX::AnnounceOnResetDevice"); + CLog::LogF(LOGDEBUG, "Reset Device Announce"); for (std::vector<IDispResource*>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) (*i)->OnResetDisplay(); } @@ -600,7 +590,7 @@ void CWinSystemOSX::StartLostDeviceTimer() if (m_lostDeviceTimer.IsRunning()) m_lostDeviceTimer.Restart(); else - m_lostDeviceTimer.Start(std::chrono::milliseconds(3000), false); + m_lostDeviceTimer.Start(3000ms, false); } void CWinSystemOSX::StopLostDeviceTimer() @@ -633,7 +623,7 @@ bool CWinSystemOSX::DestroyWindowSystem() if (m_glView) { - m_glView = NULL; + m_glView = nullptr; } UnblankDisplays(); @@ -660,7 +650,7 @@ bool CWinSystemOSX::CreateNewWindow(const std::string& name, bool fullScreen, RE // for native fullscreen we always want to set the // same windowed flags - __block NSUInteger windowStyleMask; + NSUInteger windowStyleMask; if (fullScreen) windowStyleMask = NSWindowStyleMaskBorderless; else @@ -744,7 +734,7 @@ bool CWinSystemOSX::DestroyWindowInternal() if (m_appWindow) { NSWindow* oldAppWindow = m_appWindow; - m_appWindow = NULL; + m_appWindow = nullptr; dispatch_sync(dispatch_get_main_queue(), ^{ [oldAppWindow setContentView:nil]; }); @@ -879,21 +869,12 @@ bool CWinSystemOSX::ResizeWindow(int newWidth, int newHeight, int newLeft, int n bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) { - CSingleLock lock(m_critSection); - - static NSPoint last_window_origin; - - static NSSize last_view_size; - static NSPoint last_view_origin; + std::unique_lock<CCriticalSection> lock(m_critSection); // if (m_lastDisplayNr == -1) // m_lastDisplayNr = res.iScreen; __block NSWindow* window = m_appWindow; - __block OSXGLView* view; - dispatch_sync(dispatch_get_main_queue(), ^{ - view = window.contentView; - }); const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings(); m_lastDisplayNr = GetDisplayIndex(settings->GetString(CSettings::SETTING_VIDEOSCREEN_MONITOR)); @@ -923,53 +904,29 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl if (m_bFullScreen) { - // Save info about the windowed context so we can restore it when returning to windowed. - __block NSPoint block_last_window_origin; - __block NSSize block_last_view_size; - __block NSPoint block_last_view_origin; - - dispatch_sync(dispatch_get_main_queue(), ^{ - block_last_view_size = view.frame.size; - block_last_view_origin = view.frame.origin; - block_last_window_origin = window.frame.origin; - }); - - last_view_size = block_last_view_size; - last_view_origin = block_last_view_origin; - last_window_origin = block_last_window_origin; - // This is Cocoa Windowed FullScreen Mode // Get the screen rect of our current display NSScreen* pScreen = [NSScreen.screens objectAtIndex:m_lastDisplayNr]; - NSRect screenRect = pScreen.frame; // remove frame origin offset of original display - screenRect.origin = NSZeroPoint; + pScreen.frame.origin = NSZeroPoint; - window = m_appWindow; dispatch_sync(dispatch_get_main_queue(), ^{ - view = [window contentView]; - [view setFrameSize:NSMakeSize(m_nWidth, m_nHeight)]; - - NSString* title = [NSString stringWithFormat:@"%s", ""]; - window.title = title; + [window.contentView setFrameSize:NSMakeSize(m_nWidth, m_nHeight)]; + window.title = @""; + [window setAllowsConcurrentViewDrawing:YES]; }); - // Hide the menu bar. - SetMenuBarVisible(false); - // Blank other displays if requested. if (blankOtherDisplays) BlankOtherDisplays(m_lastDisplayNr); - - dispatch_sync(dispatch_get_main_queue(), ^{ - [window setAllowsConcurrentViewDrawing:YES]; - }); } else { // Show menubar. - SetMenuBarVisible(true); + dispatch_sync(dispatch_get_main_queue(), ^{ + [NSApplication.sharedApplication setPresentationOptions:NSApplicationPresentationDefault]; + }); // Unblank. // Force the unblank when returning from fullscreen, we get called with blankOtherDisplays set false. @@ -998,7 +955,8 @@ void CWinSystemOSX::UpdateResolutions() CWinSystemBase::UpdateResolutions(); // Add desktop resolution - int w, h; + int w; + int h; double fps; int dispIdx = GetDisplayIndex(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( @@ -1024,7 +982,7 @@ void CWinSystemOSX::GetScreenResolution(int* w, int* h, double* fps, int screenI *h = CGDisplayModeGetHeight(mode); *fps = CGDisplayModeGetRefreshRate(mode); CGDisplayModeRelease(mode); - if ((int)*fps == 0) + if (static_cast<int>(*fps) == 0) { // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. *fps = 60.0; @@ -1035,8 +993,7 @@ void CWinSystemOSX::GetScreenResolution(int* w, int* h, double* fps, int screenI bool CWinSystemOSX::SwitchToVideoMode(int width, int height, double refreshrate) { - boolean_t match = false; - CGDisplayModeRef dispMode = NULL; + CGDisplayModeRef dispMode = nullptr; int screenIdx = GetDisplayIndex(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_VIDEOSCREEN_MONITOR)); @@ -1051,30 +1008,28 @@ bool CWinSystemOSX::SwitchToVideoMode(int width, int height, double refreshrate) //not found - fallback to bestemdeforparameters if (!dispMode) { - dispMode = BestMatchForMode(display_id, 32, width, height, match); + dispMode = BestMatchForMode(display_id, 32, width, height); - if (!match) - dispMode = BestMatchForMode(display_id, 16, width, height, match); - - // still no match? fallback to current resolution of the display which HAS to work [tm] - if (!match) + if (!dispMode) { - int tmpWidth; - int tmpHeight; - double tmpRefresh; - - GetScreenResolution(&tmpWidth, &tmpHeight, &tmpRefresh, screenIdx); - dispMode = GetMode(tmpWidth, tmpHeight, tmpRefresh, screenIdx); + dispMode = BestMatchForMode(display_id, 16, width, height); - // no way to get a resolution set + // still no match? fallback to current resolution of the display which HAS to work [tm] if (!dispMode) - return false; - } + { + int currentWidth; + int currentHeight; + double currentRefresh; - if (!match) - return false; - } + GetScreenResolution(¤tWidth, ¤tHeight, ¤tRefresh, screenIdx); + dispMode = GetMode(currentWidth, currentHeight, currentRefresh, screenIdx); + // no way to get a resolution set + if (!dispMode) + return false; + } + } + } // switch mode and return success CGDisplayCapture(display_id); CGDisplayConfigRef cfg; @@ -1095,15 +1050,11 @@ void CWinSystemOSX::FillInVideoModes() int dispIdx = GetDisplayIndex(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_VIDEOSCREEN_MONITOR)); - // Add full screen settings for additional monitors - int numDisplays = NSScreen.screens.count; - - for (int disp = 0; disp < numDisplays; disp++) + for (int disp = 0; disp < static_cast<int>(NSScreen.screens.count); disp++) { bool stretched; bool interlaced; bool safeForHardware; - bool televisionoutput; int w, h, bitsperpixel; double refreshrate; RESOLUTION_INFO res; @@ -1111,9 +1062,9 @@ void CWinSystemOSX::FillInVideoModes() CFArrayRef displayModes = GetAllDisplayModes(GetDisplayID(disp)); NSString* dispName = screenNameForDisplay(GetDisplayID(disp)); - CLog::Log(LOGINFO, "Display %i has name %s", disp, [dispName UTF8String]); + CLog::LogF(LOGINFO, "Display {} has name {}", disp, [dispName UTF8String]); - if (nullptr == displayModes) + if (!displayModes) continue; for (int i = 0; i < CFArrayGetCount(displayModes); ++i) @@ -1121,11 +1072,10 @@ void CWinSystemOSX::FillInVideoModes() CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, i); uint32_t flags = CGDisplayModeGetIOFlags(displayMode); - stretched = flags & kDisplayModeStretchedFlag ? true : false; - interlaced = flags & kDisplayModeInterlacedFlag ? true : false; + stretched = (flags & kDisplayModeStretchedFlag) != 0; + interlaced = (flags & kDisplayModeInterlacedFlag) != 0; bitsperpixel = DisplayBitsPerPixelForMode(displayMode); - safeForHardware = flags & kDisplayModeSafetyFlags ? true : false; - televisionoutput = flags & kDisplayModeTelevisionFlag ? true : false; + safeForHardware = (flags & kDisplayModeSafetyFlags) != 0; if ((bitsperpixel == 32) && (safeForHardware == true) && (stretched == false) && (interlaced == false)) @@ -1138,7 +1088,7 @@ void CWinSystemOSX::FillInVideoModes() // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. refreshrate = 60.0; } - CLog::Log(LOGINFO, "Found possible resolution for display %d with %d x %d @ %f Hz", disp, w, + CLog::Log(LOGINFO, "Found possible resolution for display {} with {} x {} @ {} Hz", disp, w, h, refreshrate); // only add the resolution if it belongs to "our" screen @@ -1158,17 +1108,17 @@ void CWinSystemOSX::FillInVideoModes() #pragma mark - Occlusion -bool CWinSystemOSX::IsObscured(void) +bool CWinSystemOSX::IsObscured() { if (m_obscured) - CLog::Log(LOGDEBUG, "CWinSystemOSX::IsObscured(void) - TRUE"); + CLog::LogF(LOGDEBUG, "Obscured"); return m_obscured; } void CWinSystemOSX::SetOcclusionState(bool occluded) { // m_obscured = occluded; - // CLog::Log(LOGDEBUG, "CWinSystemOSX::SetOcclusionState(bool occluded) - %s", occluded ? "true":"false"); + // CLog::LogF(LOGDEBUG, "{}", occluded ? "true":"false"); } void CWinSystemOSX::NotifyAppFocusChange(bool bGaining) @@ -1190,7 +1140,6 @@ void CWinSystemOSX::NotifyAppFocusChange(bool bGaining) window = view.window; if (window) { - SetMenuBarVisible(false); [window orderFront:nil]; } } @@ -1204,8 +1153,8 @@ void CWinSystemOSX::OnMove(int x, int y) { static double oldRefreshRate = m_refreshRate; Cocoa_CVDisplayLinkUpdate(); - int dummy = 0; + int dummy = 0; GetScreenResolution(&dummy, &dummy, &m_refreshRate, m_lastDisplayNr); if (oldRefreshRate != m_refreshRate) @@ -1215,8 +1164,8 @@ void CWinSystemOSX::OnMove(int x, int y) // send a message so that videoresolution (and refreshrate) is changed NSWindow* win = m_appWindow; NSRect frame = win.contentView.frame; - KODI::MESSAGING::CApplicationMessenger::GetInstance().PostMsg( - TMSG_VIDEORESIZE, frame.size.width, frame.size.height); + CServiceBroker::GetAppMessenger()->PostMsg(TMSG_VIDEORESIZE, frame.size.width, + frame.size.height); } } @@ -1260,7 +1209,7 @@ CGLContextObj CWinSystemOSX::GetCGLContextObj() return cglcontex; } -bool CWinSystemOSX::FlushBuffer(void) +bool CWinSystemOSX::FlushBuffer() { if (m_appWindow) { @@ -1285,8 +1234,7 @@ void CWinSystemOSX::EnableVSync(bool enable) std::unique_ptr<CVideoSync> CWinSystemOSX::GetVideoSync(void* clock) { - std::unique_ptr<CVideoSync> pVSync(new CVideoSyncOsx(clock)); - return pVSync; + return std::make_unique<CVideoSyncOsx>(clock); } std::vector<std::string> CWinSystemOSX::GetConnectedOutputs() @@ -1309,7 +1257,7 @@ std::vector<std::string> CWinSystemOSX::GetConnectedOutputs() std::unique_ptr<IOSScreenSaver> CWinSystemOSX::GetOSScreenSaverImpl() { - return std::unique_ptr<IOSScreenSaver>(new COSScreenSaverOSX); + return std::make_unique<COSScreenSaverOSX>(); } #pragma mark - Input @@ -1329,7 +1277,7 @@ void CWinSystemOSX::disableInputEvents() m_winEvents->disableInputEvents(); } -std::string CWinSystemOSX::GetClipboardText(void) +std::string CWinSystemOSX::GetClipboardText() { std::string utf8_text; |