diff --git a/app/backend/systemproperties.cpp b/app/backend/systemproperties.cpp index 4c58e2b1..8026721d 100644 --- a/app/backend/systemproperties.cpp +++ b/app/backend/systemproperties.cpp @@ -68,12 +68,6 @@ SystemProperties::SystemProperties() hasDiscordIntegration = false; #endif -#ifdef Q_OS_DARWIN - supportsWindowedSystemKeyCapture = false; -#else - supportsWindowedSystemKeyCapture = true; -#endif - unmappedGamepads = SdlInputHandler::getUnmappedGamepads(); // Populate data that requires talking to SDL. We do it all in one shot diff --git a/app/backend/systemproperties.h b/app/backend/systemproperties.h index 90ce31f2..0ee6541a 100644 --- a/app/backend/systemproperties.h +++ b/app/backend/systemproperties.h @@ -19,7 +19,6 @@ public: Q_PROPERTY(bool hasWindowManager MEMBER hasWindowManager CONSTANT) Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT) Q_PROPERTY(bool hasDiscordIntegration MEMBER hasDiscordIntegration CONSTANT) - Q_PROPERTY(bool supportsWindowedSystemKeyCapture MEMBER supportsWindowedSystemKeyCapture CONSTANT) Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged) Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT) Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution CONSTANT) @@ -44,7 +43,6 @@ private: bool hasWindowManager; bool hasBrowser; bool hasDiscordIntegration; - bool supportsWindowedSystemKeyCapture; QString unmappedGamepads; int maximumStreamingFrameRate; QSize maximumResolution; diff --git a/app/gui/SettingsView.qml b/app/gui/SettingsView.qml index 53c99009..ec0fd28f 100644 --- a/app/gui/SettingsView.qml +++ b/app/gui/SettingsView.qml @@ -911,8 +911,7 @@ Flickable { id: captureSysKeysCheck hoverEnabled: true width: parent.width - text: qsTr("Capture system keyboard shortcuts") + (SystemProperties.supportsWindowedSystemKeyCapture ? - "" : qsTr(" while streaming in fullscreen mode")) + text: qsTr("Capture system keyboard shortcuts") font.pointSize: 12 enabled: SystemProperties.hasWindowManager checked: StreamingPreferences.captureSysKeys && SystemProperties.hasWindowManager diff --git a/app/streaming/input/input.cpp b/app/streaming/input/input.cpp index 74eae418..38c4c602 100644 --- a/app/streaming/input/input.cpp +++ b/app/streaming/input/input.cpp @@ -171,6 +171,10 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s } #endif +#ifdef Q_OS_DARWIN + CGSGetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), &m_OldHotKeyMode); +#endif + // Initialize the gamepad mask with currently attached gamepads to avoid // causing gamepads to unexpectedly disappear and reappear on the host // during stream startup as we detect currently attached gamepads one at a time. @@ -240,6 +244,10 @@ SdlInputHandler::~SdlInputHandler() SDL_DestroyCond(m_ClipboardHasData); SDL_DestroyMutex(m_ClipboardLock); +#ifdef Q_OS_DARWIN + CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode); +#endif + #if !SDL_VERSION_ATLEAST(2, 0, 9) SDL_QuitSubSystem(SDL_INIT_HAPTIC); SDL_assert(!SDL_WasInit(SDL_INIT_HAPTIC)); @@ -319,11 +327,28 @@ void SdlInputHandler::notifyFocusLost() setCaptureActive(false); } +#ifdef Q_OS_DARWIN + if (m_CaptureSystemKeysEnabled) { + // Stop capturing system keys on focus loss + CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode); + } +#endif + // Raise all keys that are currently pressed. If we don't do this, certain keys // used in shortcuts that cause focus loss (such as Alt+Tab) may get stuck down. raiseAllKeys(); } +void SdlInputHandler::notifyFocusGained() +{ +#ifdef Q_OS_DARWIN + if (m_CaptureSystemKeysEnabled) { + // Start capturing system keys again on focus gain + CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), CGSGlobalHotKeyDisable); + } +#endif +} + bool SdlInputHandler::isCaptureActive() { if (SDL_GetRelativeMouseMode()) { @@ -350,10 +375,6 @@ bool SdlInputHandler::isSystemKeyCaptureActive() && (windowFlags & SDL_WINDOW_KEYBOARD_GRABBED) #else && (windowFlags & SDL_WINDOW_INPUT_GRABBED) -#endif -#ifdef Q_OS_DARWIN - // Darwin only supports full-screen system key capture - && (windowFlags & SDL_WINDOW_FULLSCREEN) #endif ; } @@ -383,6 +404,10 @@ void SdlInputHandler::setCaptureActive(bool active) if (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN) { SDL_SetWindowGrab(m_Window, SDL_TRUE); } +#endif +#ifdef Q_OS_DARWIN + // SDL doesn't support this private macOS API + CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), CGSGlobalHotKeyDisable); #endif } @@ -440,6 +465,11 @@ void SdlInputHandler::setCaptureActive(bool active) // Allow the cursor to leave the bounds of our window again. SDL_SetWindowGrab(m_Window, SDL_FALSE); #endif + +#ifdef Q_OS_DARWIN + // SDL doesn't support this private macOS API + CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode); +#endif } } diff --git a/app/streaming/input/input.h b/app/streaming/input/input.h index 01b997a4..823f502d 100644 --- a/app/streaming/input/input.h +++ b/app/streaming/input/input.h @@ -29,6 +29,25 @@ struct GamepadState { unsigned char lt, rt; }; +#ifdef Q_OS_DARWIN +#include +extern "C" { + typedef int CGSConnection; + typedef enum { + CGSGlobalHotKeyEnable = 0, + CGSGlobalHotKeyDisable = 1, + } CGSGlobalHotKeyOperatingMode; + + extern CGSConnection _CGSDefaultConnection(void); + + extern CGError CGSGetGlobalHotKeyOperatingMode(CGSConnection connection, + CGSGlobalHotKeyOperatingMode* mode); + + extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, + CGSGlobalHotKeyOperatingMode mode); +} +#endif + #define MAX_GAMEPADS 4 #define MAX_FINGERS 2 @@ -79,6 +98,8 @@ public: void notifyFocusLost(); + void notifyFocusGained(); + bool isCaptureActive(); bool isSystemKeyCaptureActive(); @@ -167,6 +188,10 @@ private: bool m_CaptureSystemKeysEnabled; int m_MouseCursorCapturedVisibilityState; +#ifdef Q_OS_DARWIN + CGSGlobalHotKeyOperatingMode m_OldHotKeyMode; +#endif + struct { KeyCombo keyCombo; SDL_Keycode keyCode; diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 67ee0c0d..fc0013c0 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -522,15 +522,6 @@ bool Session::initialize() break; } -#ifdef Q_OS_DARWIN - // macOS behaves as if we're capturing system keys when - // we enter "real" full-screen mode, so use standard - // full-screen as our full-screen flag when capturing keys. - if (m_Preferences->captureSysKeys) { - m_FullScreenFlag = SDL_WINDOW_FULLSCREEN; - } -#endif - #if !SDL_VERSION_ATLEAST(2, 0, 11) // HACK: Using a full-screen window breaks mouse capture on the Pi's LXDE // GUI environment. Force the session to use windowed mode (which won't @@ -1345,6 +1336,7 @@ void Session::exec(int displayOriginX, int displayOriginY) if (m_Preferences->muteOnFocusLoss) { m_AudioMuted = false; } + m_InputHandler->notifyFocusGained(); break; case SDL_WINDOWEVENT_LEAVE: m_InputHandler->notifyMouseLeave();