Add support for system key capture in windowed mode on macOS

This commit is contained in:
Cameron Gutman 2021-02-26 21:43:47 -06:00
parent 28ecc6bcbf
commit b27ca993aa
6 changed files with 61 additions and 23 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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
}
}

View File

@ -29,6 +29,25 @@ struct GamepadState {
unsigned char lt, rt;
};
#ifdef Q_OS_DARWIN
#include <CoreGraphics/CGError.h>
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;

View File

@ -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();