Add setting to only capture system keys in full-screen

This commit is contained in:
Cameron Gutman 2021-02-27 16:47:38 -06:00
parent 58803ef40d
commit 87a7d2e45c
8 changed files with 187 additions and 72 deletions

View File

@ -264,6 +264,11 @@ StreamCommandLineParser::StreamCommandLineParser()
{"software", StreamingPreferences::VDS_FORCE_SOFTWARE}, {"software", StreamingPreferences::VDS_FORCE_SOFTWARE},
{"hardware", StreamingPreferences::VDS_FORCE_HARDWARE}, {"hardware", StreamingPreferences::VDS_FORCE_HARDWARE},
}; };
m_CaptureSysKeysModeMap = {
{"never", StreamingPreferences::CSK_OFF},
{"fullscreen", StreamingPreferences::CSK_FULLSCREEN},
{"always", StreamingPreferences::CSK_ALWAYS},
};
} }
StreamCommandLineParser::~StreamCommandLineParser() StreamCommandLineParser::~StreamCommandLineParser()
@ -307,7 +312,7 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
parser.addToggleOption("background-gamepad", "background gamepad input"); parser.addToggleOption("background-gamepad", "background gamepad input");
parser.addToggleOption("reverse-scroll-direction", "inverted scroll direction"); parser.addToggleOption("reverse-scroll-direction", "inverted scroll direction");
parser.addToggleOption("swap-gamepad-buttons", "swap A/B and X/Y gamepad buttons (Nintendo-style)"); parser.addToggleOption("swap-gamepad-buttons", "swap A/B and X/Y gamepad buttons (Nintendo-style)");
parser.addToggleOption("capture-system-keys", "capture system key combos in fullscreen mode"); parser.addChoiceOption("capture-system-keys", "capture system key combos", m_CaptureSysKeysModeMap.keys());
parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys()); parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys());
parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys()); parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys());
@ -422,8 +427,10 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
// Resolve --swap-gamepad-buttons and --no-swap-gamepad-buttons options // Resolve --swap-gamepad-buttons and --no-swap-gamepad-buttons options
preferences->swapFaceButtons = parser.getToggleOptionValue("swap-gamepad-buttons", preferences->swapFaceButtons); preferences->swapFaceButtons = parser.getToggleOptionValue("swap-gamepad-buttons", preferences->swapFaceButtons);
// Resolve --capture-system-keys and --no-capture-system-keys options // Resolve --capture-system-keys option
preferences->captureSysKeys = parser.getToggleOptionValue("capture-system-keys", preferences->captureSysKeys); if (parser.isSet("capture-system-keys")) {
preferences->captureSysKeysMode = mapValue(m_CaptureSysKeysModeMap, parser.getChoiceOptionValue("capture-system-keys"));
}
// Resolve --video-codec option // Resolve --video-codec option
if (parser.isSet("video-codec")) { if (parser.isSet("video-codec")) {

View File

@ -53,4 +53,5 @@ private:
QMap<QString, StreamingPreferences::AudioConfig> m_AudioConfigMap; QMap<QString, StreamingPreferences::AudioConfig> m_AudioConfigMap;
QMap<QString, StreamingPreferences::VideoCodecConfig> m_VideoCodecMap; QMap<QString, StreamingPreferences::VideoCodecConfig> m_VideoCodecMap;
QMap<QString, StreamingPreferences::VideoDecoderSelection> m_VideoDecoderMap; QMap<QString, StreamingPreferences::VideoDecoderSelection> m_VideoDecoderMap;
QMap<QString, StreamingPreferences::CaptureSysKeysMode> m_CaptureSysKeysModeMap;
}; };

View File

@ -907,23 +907,79 @@ Flickable {
qsTr("NOTE: Due to a bug in GeForce Experience, this option may not work properly if your host PC has multiple monitors.") qsTr("NOTE: Due to a bug in GeForce Experience, this option may not work properly if your host PC has multiple monitors.")
} }
CheckBox { Row {
id: captureSysKeysCheck spacing: 5
hoverEnabled: true
width: parent.width width: parent.width
text: qsTr("Capture system keyboard shortcuts")
font.pointSize: 12 CheckBox {
enabled: SystemProperties.hasWindowManager id: captureSysKeysCheck
checked: StreamingPreferences.captureSysKeys && SystemProperties.hasWindowManager hoverEnabled: true
onCheckedChanged: { text: qsTr("Capture system keyboard shortcuts")
StreamingPreferences.captureSysKeys = checked font.pointSize: 12
enabled: SystemProperties.hasWindowManager
checked: StreamingPreferences.captureSysKeysMode !== StreamingPreferences.CSK_OFF || !SystemProperties.hasWindowManager
ToolTip.delay: 1000
ToolTip.timeout: 10000
ToolTip.visible: hovered
ToolTip.text: qsTr("This enables the capture of system-wide keyboard shortcuts like Alt+Tab that would normally be handled by the client OS while streaming.") + "\n\n" +
qsTr("NOTE: Certain keyboard shortcuts like Ctrl+Alt+Del on Windows cannot be intercepted by any application, including Moonlight.")
} }
ToolTip.delay: 1000 AutoResizingComboBox {
ToolTip.timeout: 10000 // ignore setting the index at first, and actually set it when the component is loaded
ToolTip.visible: hovered Component.onCompleted: {
ToolTip.text: qsTr("This enables the capture of system-wide keyboard shortcuts like Alt+Tab that would normally be handled by the client OS while streaming.") + "\n\n" + if (!visible) {
qsTr("NOTE: Certain keyboard shortcuts like Ctrl+Alt+Del on Windows cannot be intercepted by any application, including Moonlight.") // Do nothing if the control won't even be visible
return
}
var saved_syskeysmode = StreamingPreferences.captureSysKeysMode
currentIndex = 0
for (var i = 0; i < captureSysKeysModeListModel.count; i++) {
var el_syskeysmode = captureSysKeysModeListModel.get(i).val;
if (saved_syskeysmode === el_syskeysmode) {
currentIndex = i
break
}
}
activated(currentIndex)
}
enabled: captureSysKeysCheck.checked
textRole: "text"
model: ListModel {
id: captureSysKeysModeListModel
ListElement {
text: qsTr("in fullscreen")
val: StreamingPreferences.CSK_FULLSCREEN
}
ListElement {
text: qsTr("always")
val: StreamingPreferences.CSK_ALWAYS
}
}
function updatePref() {
if (!enabled) {
StreamingPreferences.captureSysKeysMode = StreamingPreferences.CSK_OFF
}
else {
StreamingPreferences.captureSysKeysMode = captureSysKeysModeListModel.get(currentIndex).val
}
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated: {
updatePref()
}
// This handles transition of the checkbox state
onEnabledChanged: {
updatePref()
}
}
} }
CheckBox { CheckBox {

View File

@ -95,7 +95,8 @@ void StreamingPreferences::reload()
backgroundGamepad = settings.value(SER_BACKGROUNDGAMEPAD, false).toBool(); backgroundGamepad = settings.value(SER_BACKGROUNDGAMEPAD, false).toBool();
reverseScrollDirection = settings.value(SER_REVERSESCROLL, false).toBool(); reverseScrollDirection = settings.value(SER_REVERSESCROLL, false).toBool();
swapFaceButtons = settings.value(SER_SWAPFACEBUTTONS, false).toBool(); swapFaceButtons = settings.value(SER_SWAPFACEBUTTONS, false).toBool();
captureSysKeys = settings.value(SER_CAPTURESYSKEYS, false).toBool(); captureSysKeysMode = static_cast<CaptureSysKeysMode>(settings.value(SER_CAPTURESYSKEYS,
static_cast<int>(CaptureSysKeysMode::CSK_OFF)).toInt());
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG, audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
static_cast<int>(AudioConfig::AC_STEREO)).toInt()); static_cast<int>(AudioConfig::AC_STEREO)).toInt());
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG, videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
@ -227,7 +228,7 @@ void StreamingPreferences::save()
settings.setValue(SER_BACKGROUNDGAMEPAD, backgroundGamepad); settings.setValue(SER_BACKGROUNDGAMEPAD, backgroundGamepad);
settings.setValue(SER_REVERSESCROLL, reverseScrollDirection); settings.setValue(SER_REVERSESCROLL, reverseScrollDirection);
settings.setValue(SER_SWAPFACEBUTTONS, swapFaceButtons); settings.setValue(SER_SWAPFACEBUTTONS, swapFaceButtons);
settings.setValue(SER_CAPTURESYSKEYS, captureSysKeys); settings.setValue(SER_CAPTURESYSKEYS, captureSysKeysMode);
} }
int StreamingPreferences::getDefaultBitrate(int width, int height, int fps) int StreamingPreferences::getDefaultBitrate(int width, int height, int fps)

View File

@ -69,6 +69,14 @@ public:
}; };
Q_ENUM(Language); Q_ENUM(Language);
enum CaptureSysKeysMode
{
CSK_OFF,
CSK_FULLSCREEN,
CSK_ALWAYS,
};
Q_ENUM(CaptureSysKeysMode);
Q_PROPERTY(int width MEMBER width NOTIFY displayModeChanged) Q_PROPERTY(int width MEMBER width NOTIFY displayModeChanged)
Q_PROPERTY(int height MEMBER height NOTIFY displayModeChanged) Q_PROPERTY(int height MEMBER height NOTIFY displayModeChanged)
Q_PROPERTY(int fps MEMBER fps NOTIFY displayModeChanged) Q_PROPERTY(int fps MEMBER fps NOTIFY displayModeChanged)
@ -98,7 +106,7 @@ public:
Q_PROPERTY(bool backgroundGamepad MEMBER backgroundGamepad NOTIFY backgroundGamepadChanged) Q_PROPERTY(bool backgroundGamepad MEMBER backgroundGamepad NOTIFY backgroundGamepadChanged)
Q_PROPERTY(bool reverseScrollDirection MEMBER reverseScrollDirection NOTIFY reverseScrollDirectionChanged) Q_PROPERTY(bool reverseScrollDirection MEMBER reverseScrollDirection NOTIFY reverseScrollDirectionChanged)
Q_PROPERTY(bool swapFaceButtons MEMBER swapFaceButtons NOTIFY swapFaceButtonsChanged) Q_PROPERTY(bool swapFaceButtons MEMBER swapFaceButtons NOTIFY swapFaceButtonsChanged)
Q_PROPERTY(bool captureSysKeys MEMBER captureSysKeys NOTIFY captureSysKeysChanged) Q_PROPERTY(CaptureSysKeysMode captureSysKeysMode MEMBER captureSysKeysMode NOTIFY captureSysKeysModeChanged)
Q_PROPERTY(Language language MEMBER language NOTIFY languageChanged); Q_PROPERTY(Language language MEMBER language NOTIFY languageChanged);
Q_INVOKABLE bool retranslate(); Q_INVOKABLE bool retranslate();
@ -127,7 +135,6 @@ public:
bool backgroundGamepad; bool backgroundGamepad;
bool reverseScrollDirection; bool reverseScrollDirection;
bool swapFaceButtons; bool swapFaceButtons;
bool captureSysKeys;
int packetSize; int packetSize;
AudioConfig audioConfig; AudioConfig audioConfig;
VideoCodecConfig videoCodecConfig; VideoCodecConfig videoCodecConfig;
@ -136,6 +143,7 @@ public:
WindowMode recommendedFullScreenMode; WindowMode recommendedFullScreenMode;
UIDisplayMode uiDisplayMode; UIDisplayMode uiDisplayMode;
Language language; Language language;
CaptureSysKeysMode captureSysKeysMode;
signals: signals:
void displayModeChanged(); void displayModeChanged();
@ -164,7 +172,7 @@ signals:
void backgroundGamepadChanged(); void backgroundGamepadChanged();
void reverseScrollDirectionChanged(); void reverseScrollDirectionChanged();
void swapFaceButtonsChanged(); void swapFaceButtonsChanged();
void captureSysKeysChanged(); void captureSysKeysModeChanged();
void languageChanged(); void languageChanged();
private: private:

View File

@ -22,7 +22,7 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_MouseWasInVideoRegion(false), m_MouseWasInVideoRegion(false),
m_PendingMouseButtonsAllUpOnVideoRegionLeave(false), m_PendingMouseButtonsAllUpOnVideoRegionLeave(false),
m_FakeCaptureActive(false), m_FakeCaptureActive(false),
m_CaptureSystemKeysEnabled(prefs.captureSysKeys || !WMUtils::isRunningWindowManager()), m_CaptureSystemKeysMode(prefs.captureSysKeysMode),
m_MouseCursorCapturedVisibilityState(SDL_DISABLE), m_MouseCursorCapturedVisibilityState(SDL_DISABLE),
m_PendingKeyCombo(KeyComboMax), m_PendingKeyCombo(KeyComboMax),
m_LongPressTimer(0), m_LongPressTimer(0),
@ -37,6 +37,11 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_NumFingersDown(0), m_NumFingersDown(0),
m_ClipboardData() m_ClipboardData()
{ {
// System keys are always captured when running without a WM
if (!WMUtils::isRunningWindowManager()) {
m_CaptureSystemKeysMode = StreamingPreferences::CSK_ALWAYS;
}
// Allow gamepad input when the app doesn't have focus if requested // Allow gamepad input when the app doesn't have focus if requested
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, prefs.backgroundGamepad ? "1" : "0"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, prefs.backgroundGamepad ? "1" : "0");
@ -51,16 +56,13 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
#if !SDL_VERSION_ATLEAST(2, 0, 15) #if !SDL_VERSION_ATLEAST(2, 0, 15)
// For older versions of SDL (2.0.14 and earlier), use SDL_HINT_GRAB_KEYBOARD // For older versions of SDL (2.0.14 and earlier), use SDL_HINT_GRAB_KEYBOARD
SDL_SetHintWithPriority(SDL_HINT_GRAB_KEYBOARD, SDL_SetHintWithPriority(SDL_HINT_GRAB_KEYBOARD,
m_CaptureSystemKeysEnabled ? "1" : "0", m_CaptureSystemKeysMode != StreamingPreferences::CSK_OFF ? "1" : "0",
SDL_HINT_OVERRIDE); SDL_HINT_OVERRIDE);
#endif #endif
// Opt-out of SDL's built-in Alt+Tab handling while keyboard grab is enabled // Opt-out of SDL's built-in Alt+Tab handling while keyboard grab is enabled
SDL_SetHint("SDL_ALLOW_ALT_TAB_WHILE_GRABBED", "0"); SDL_SetHint("SDL_ALLOW_ALT_TAB_WHILE_GRABBED", "0");
// Don't close the window on Alt+F4 when keyboard grab is enabled
SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, m_CaptureSystemKeysEnabled ? "1" : "0");
// Allow clicks to pass through to us when focusing the window. If we're in // Allow clicks to pass through to us when focusing the window. If we're in
// absolute mouse mode, this will avoid the user having to click twice to // absolute mouse mode, this will avoid the user having to click twice to
// trigger a click on the host if the Moonlight window is not focused. In // trigger a click on the host if the Moonlight window is not focused. In
@ -328,10 +330,8 @@ void SdlInputHandler::notifyFocusLost()
} }
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
if (m_CaptureSystemKeysEnabled) { // Ungrab the keyboard
// Stop capturing system keys on focus loss updateKeyboardGrabState();
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode);
}
#endif #endif
// Raise all keys that are currently pressed. If we don't do this, certain keys // Raise all keys that are currently pressed. If we don't do this, certain keys
@ -342,10 +342,11 @@ void SdlInputHandler::notifyFocusLost()
void SdlInputHandler::notifyFocusGained() void SdlInputHandler::notifyFocusGained()
{ {
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
if (m_CaptureSystemKeysEnabled) { // Re-grab the keyboard if it was grabbed before focus loss
// Start capturing system keys again on focus gain // FIXME: We only do this on macOS because we get a spurious
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), CGSGlobalHotKeyDisable); // focus gain when in SDL_WINDOW_FULLSCREEN_DESKTOP on Windows
} // immediately after losing focus by clicking on another window.
updateKeyboardGrabState();
#endif #endif
} }
@ -359,9 +360,62 @@ bool SdlInputHandler::isCaptureActive()
return m_FakeCaptureActive; return m_FakeCaptureActive;
} }
void SdlInputHandler::updateKeyboardGrabState()
{
if (m_CaptureSystemKeysMode == StreamingPreferences::CSK_OFF) {
return;
}
bool shouldGrab = isCaptureActive();
Uint32 windowFlags = SDL_GetWindowFlags(m_Window);
if (m_CaptureSystemKeysMode == StreamingPreferences::CSK_FULLSCREEN &&
!(windowFlags & SDL_WINDOW_FULLSCREEN)) {
// Ungrab if it's fullscreen only and we left fullscreen
shouldGrab = false;
}
else if (!(windowFlags & SDL_WINDOW_INPUT_FOCUS)) {
// Ungrab if we lose input focus (SDL will do this internally, but
// not for macOS where SDL is not handling the grab logic).
shouldGrab = false;
}
// Don't close the window on Alt+F4 when keyboard grab is enabled
SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, shouldGrab ? "1" : "0");
if (shouldGrab) {
#if SDL_VERSION_ATLEAST(2, 0, 15)
// On SDL 2.0.15, we can get keyboard-only grab on Win32, X11, and Wayland.
// This does nothing on macOS but it sets the SDL_WINDOW_KEYBOARD_GRABBED flag
// that we look for to see if keyboard capture is enabled. We'll handle macOS
// ourselves below using the private CGSSetGlobalHotKeyOperatingMode() API.
SDL_SetWindowKeyboardGrab(m_Window, SDL_TRUE);
#else
// If we're in full-screen desktop mode and SDL doesn't have keyboard grab yet,
// grab the cursor (will grab the keyboard too on X11).
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
}
else {
#if SDL_VERSION_ATLEAST(2, 0, 15)
// Allow the keyboard to leave the window
SDL_SetWindowKeyboardGrab(m_Window, SDL_FALSE);
#endif
#ifdef Q_OS_DARWIN
// SDL doesn't support this private macOS API
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode);
#endif
}
}
bool SdlInputHandler::isSystemKeyCaptureActive() bool SdlInputHandler::isSystemKeyCaptureActive()
{ {
if (!m_CaptureSystemKeysEnabled) { if (m_CaptureSystemKeysMode == StreamingPreferences::CSK_OFF) {
return false; return false;
} }
@ -370,13 +424,23 @@ bool SdlInputHandler::isSystemKeyCaptureActive()
} }
Uint32 windowFlags = SDL_GetWindowFlags(m_Window); Uint32 windowFlags = SDL_GetWindowFlags(m_Window);
return (windowFlags & SDL_WINDOW_INPUT_FOCUS) if (!(windowFlags & SDL_WINDOW_INPUT_FOCUS)
#if SDL_VERSION_ATLEAST(2, 0, 15) #if SDL_VERSION_ATLEAST(2, 0, 15)
&& (windowFlags & SDL_WINDOW_KEYBOARD_GRABBED) || !(windowFlags & SDL_WINDOW_KEYBOARD_GRABBED)
#else #else
&& (windowFlags & SDL_WINDOW_INPUT_GRABBED) || !(windowFlags & SDL_WINDOW_INPUT_GRABBED)
#endif #endif
; )
{
return false;
}
if (m_CaptureSystemKeysMode == StreamingPreferences::CSK_FULLSCREEN &&
!(windowFlags & SDL_WINDOW_FULLSCREEN)) {
return false;
}
return true;
} }
void SdlInputHandler::setCaptureActive(bool active) void SdlInputHandler::setCaptureActive(bool active)
@ -391,26 +455,6 @@ void SdlInputHandler::setCaptureActive(bool active)
#endif #endif
} }
// Grab the keyboard too if system key capture is enabled
if (m_CaptureSystemKeysEnabled) {
#if SDL_VERSION_ATLEAST(2, 0, 15)
// On SDL 2.0.15, we can get keyboard-only grab on Win32, X11, and Wayland.
// This does nothing on macOS but it sets the SDL_WINDOW_KEYBOARD_GRABBED flag
// that we look for to see if keyboard capture is enabled.
SDL_SetWindowKeyboardGrab(m_Window, SDL_TRUE);
#else
// If we're in full-screen desktop mode and SDL doesn't have keyboard grab yet,
// grab the cursor (will grab the keyboard too on X11).
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
}
if (!m_AbsoluteMouseMode) { if (!m_AbsoluteMouseMode) {
// If our window is occluded when mouse is captured, the mouse may // If our window is occluded when mouse is captured, the mouse may
// get stuck on top of the occluding window and not be properly // get stuck on top of the occluding window and not be properly
@ -458,19 +502,14 @@ void SdlInputHandler::setCaptureActive(bool active)
#if SDL_VERSION_ATLEAST(2, 0, 15) #if SDL_VERSION_ATLEAST(2, 0, 15)
// Allow the cursor to leave the bounds of our window again. // Allow the cursor to leave the bounds of our window again.
SDL_SetWindowMouseGrab(m_Window, SDL_FALSE); SDL_SetWindowMouseGrab(m_Window, SDL_FALSE);
// Allow the keyboard to leave the window
SDL_SetWindowKeyboardGrab(m_Window, SDL_FALSE);
#else #else
// Allow the cursor to leave the bounds of our window again. // Allow the cursor to leave the bounds of our window again.
SDL_SetWindowGrab(m_Window, SDL_FALSE); SDL_SetWindowGrab(m_Window, SDL_FALSE);
#endif #endif
#ifdef Q_OS_DARWIN
// SDL doesn't support this private macOS API
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), m_OldHotKeyMode);
#endif
} }
// Now update the keyboard grab
updateKeyboardGrabState();
} }
void SdlInputHandler::handleTouchFingerEvent(SDL_TouchFingerEvent* event) void SdlInputHandler::handleTouchFingerEvent(SDL_TouchFingerEvent* event)

View File

@ -112,6 +112,8 @@ public:
void flushMousePositionUpdate(); void flushMousePositionUpdate();
void updateKeyboardGrabState();
static static
QString getUnmappedGamepads(); QString getUnmappedGamepads();
@ -185,7 +187,7 @@ private:
bool m_FakeCaptureActive; bool m_FakeCaptureActive;
QString m_OldIgnoreDevices; QString m_OldIgnoreDevices;
QString m_OldIgnoreDevicesExcept; QString m_OldIgnoreDevicesExcept;
bool m_CaptureSystemKeysEnabled; StreamingPreferences::CaptureSysKeysMode m_CaptureSystemKeysMode;
int m_MouseCursorCapturedVisibilityState; int m_MouseCursorCapturedVisibilityState;
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN

View File

@ -926,10 +926,8 @@ void Session::toggleFullscreen()
bool fullScreen = !(SDL_GetWindowFlags(m_Window) & m_FullScreenFlag); bool fullScreen = !(SDL_GetWindowFlags(m_Window) & m_FullScreenFlag);
if (fullScreen) { if (fullScreen) {
if ((m_FullScreenFlag == SDL_WINDOW_FULLSCREEN || m_Preferences->captureSysKeys) && m_InputHandler->isCaptureActive()) { if (m_FullScreenFlag == SDL_WINDOW_FULLSCREEN && m_InputHandler->isCaptureActive()) {
// Confine the cursor to the window if we're capturing input while transitioning to full screen. // Confine the cursor to the window if we're capturing input while transitioning to full screen.
// We also need to grab if we're capturing system keys, because SDL requires window grab to
// capture the keyboard on X11.
SDL_SetWindowGrab(m_Window, SDL_TRUE); SDL_SetWindowGrab(m_Window, SDL_TRUE);
} }
@ -946,6 +944,9 @@ void Session::toggleFullscreen()
// Reposition the window when the resize is complete // Reposition the window when the resize is complete
m_PendingWindowedTransition = true; m_PendingWindowedTransition = true;
} }
// Input handler might need to start/stop keyboard grab after changing modes
m_InputHandler->updateKeyboardGrabState();
} }
void Session::notifyMouseEmulationMode(bool enabled) void Session::notifyMouseEmulationMode(bool enabled)