mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-17 14:11:33 +00:00
Provide detection and help for unmapped gamepads. Fixes #70
This commit is contained in:
@@ -46,6 +46,12 @@ GridView {
|
|||||||
noHwDecoderDialog.open()
|
noHwDecoderDialog.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unmappedGamepads = prefs.getUnmappedGamepads()
|
||||||
|
if (unmappedGamepads) {
|
||||||
|
unmappedGamepadDialog.unmappedGamepads = unmappedGamepads
|
||||||
|
unmappedGamepadDialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
// Don't show any highlighted item until interacting with them
|
// Don't show any highlighted item until interacting with them
|
||||||
currentIndex = -1
|
currentIndex = -1
|
||||||
}
|
}
|
||||||
@@ -244,6 +250,20 @@ GridView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: unmappedGamepadDialog
|
||||||
|
property string unmappedGamepads : ""
|
||||||
|
modality:Qt.WindowModal
|
||||||
|
icon: StandardIcon.Warning
|
||||||
|
standardButtons: StandardButton.Ok | StandardButton.Help
|
||||||
|
text: "Moonlight detected gamepads without a proper mapping. " +
|
||||||
|
"The following gamepads will not function until this is resolved: " + unmappedGamepads + "\n\n" +
|
||||||
|
"Click the Help button for information on how to map your gamepads."
|
||||||
|
onHelp: {
|
||||||
|
Qt.openUrlExternally("https://github.com/moonlight-stream/moonlight-docs/wiki/Gamepad-Mapping");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MessageDialog {
|
MessageDialog {
|
||||||
id: pairDialog
|
id: pairDialog
|
||||||
// don't allow edits to the rest of the window while open
|
// don't allow edits to the rest of the window while open
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ bool StreamingPreferences::isWow64()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString StreamingPreferences::getUnmappedGamepads()
|
||||||
|
{
|
||||||
|
return SdlInputHandler::getUnmappedGamepads();
|
||||||
|
}
|
||||||
|
|
||||||
int StreamingPreferences::getMaximumStreamingFrameRate()
|
int StreamingPreferences::getMaximumStreamingFrameRate()
|
||||||
{
|
{
|
||||||
// Never let the maximum drop below 60 FPS
|
// Never let the maximum drop below 60 FPS
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
||||||
|
|
||||||
|
Q_INVOKABLE QString getUnmappedGamepads();
|
||||||
|
|
||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
enum AudioConfig
|
enum AudioConfig
|
||||||
|
|||||||
+85
-2
@@ -668,9 +668,37 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SdlInputHandler::handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event)
|
||||||
|
{
|
||||||
|
SDL_assert(event->type == SDL_JOYDEVICEADDED);
|
||||||
|
|
||||||
|
if (!SDL_IsGameController(event->which)) {
|
||||||
|
char guidStr[33];
|
||||||
|
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(event->which),
|
||||||
|
guidStr, sizeof(guidStr));
|
||||||
|
const char* name = SDL_JoystickNameForIndex(event->which);
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Joystick discovered with no mapping: %s %s",
|
||||||
|
name ? name : "<UNKNOWN>",
|
||||||
|
guidStr);
|
||||||
|
SDL_Joystick* joy = SDL_JoystickOpen(event->which);
|
||||||
|
if (joy != nullptr) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Number of axes: %d | Number of buttons: %d | Number of hats: %d",
|
||||||
|
SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy),
|
||||||
|
SDL_JoystickNumHats(joy));
|
||||||
|
SDL_JoystickClose(joy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Unable to open joystick for query: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int SdlInputHandler::getAttachedGamepadMask()
|
int SdlInputHandler::getAttachedGamepadMask()
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int count;
|
int count;
|
||||||
int mask;
|
int mask;
|
||||||
|
|
||||||
@@ -680,7 +708,7 @@ int SdlInputHandler::getAttachedGamepadMask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
count = mask = 0;
|
count = mask = 0;
|
||||||
for (i = 0; i < SDL_NumJoysticks(); i++) {
|
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||||
if (SDL_IsGameController(i)) {
|
if (SDL_IsGameController(i)) {
|
||||||
mask |= (1 << count++);
|
mask |= (1 << count++);
|
||||||
}
|
}
|
||||||
@@ -688,3 +716,58 @@ int SdlInputHandler::getAttachedGamepadMask()
|
|||||||
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SdlInputHandler::getUnmappedGamepads()
|
||||||
|
{
|
||||||
|
QString ret;
|
||||||
|
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||||
|
if (!SDL_IsGameController(i)) {
|
||||||
|
char guidStr[33];
|
||||||
|
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
|
||||||
|
guidStr, sizeof(guidStr));
|
||||||
|
const char* name = SDL_JoystickNameForIndex(i);
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Unmapped joystick: %s %s",
|
||||||
|
name ? name : "<UNKNOWN>",
|
||||||
|
guidStr);
|
||||||
|
SDL_Joystick* joy = SDL_JoystickOpen(i);
|
||||||
|
if (joy != nullptr) {
|
||||||
|
int numButtons = SDL_JoystickNumButtons(joy);
|
||||||
|
int numHats = SDL_JoystickNumHats(joy);
|
||||||
|
int numAxes = SDL_JoystickNumAxes(joy);
|
||||||
|
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Number of axes: %d | Number of buttons: %d | Number of hats: %d",
|
||||||
|
numAxes, numButtons, numHats);
|
||||||
|
|
||||||
|
if (numAxes >= 4 && numButtons >= 8 && numHats <= 1) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Joystick likely to be an unmapped game controller");
|
||||||
|
if (!ret.isEmpty()) {
|
||||||
|
ret += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += name;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_JoystickClose(joy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Unable to open joystick for query: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,8 +39,13 @@ public:
|
|||||||
|
|
||||||
void handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event);
|
void handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event);
|
||||||
|
|
||||||
|
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
|
||||||
|
|
||||||
int getAttachedGamepadMask();
|
int getAttachedGamepadMask();
|
||||||
|
|
||||||
|
static
|
||||||
|
QString getUnmappedGamepads();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GamepadState*
|
GamepadState*
|
||||||
findStateForGamepad(SDL_JoystickID id);
|
findStateForGamepad(SDL_JoystickID id);
|
||||||
|
|||||||
@@ -525,6 +525,11 @@ bool Session::validateLaunch()
|
|||||||
emitLaunchWarning("Failed to open audio device. Audio will be unavailable during this session.");
|
emitLaunchWarning("Failed to open audio device. Audio will be unavailable during this session.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for unmapped gamepads
|
||||||
|
if (!SdlInputHandler::getUnmappedGamepads().isEmpty()) {
|
||||||
|
emitLaunchWarning("An attached gamepad has no mapping and won't be usable. Visit the Moonlight help to resolve this.");
|
||||||
|
}
|
||||||
|
|
||||||
if (m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_FORCE_HARDWARE &&
|
if (m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_FORCE_HARDWARE &&
|
||||||
!isHardwareDecodeAvailable(m_Preferences->videoDecoderSelection,
|
!isHardwareDecodeAvailable(m_Preferences->videoDecoderSelection,
|
||||||
m_StreamConfig.supportsHevc ? VIDEO_FORMAT_H265 : VIDEO_FORMAT_H264,
|
m_StreamConfig.supportsHevc ? VIDEO_FORMAT_H265 : VIDEO_FORMAT_H264,
|
||||||
@@ -1107,13 +1112,12 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
|||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
inputHandler.handleControllerDeviceEvent(&event.cdevice);
|
inputHandler.handleControllerDeviceEvent(&event.cdevice);
|
||||||
break;
|
break;
|
||||||
|
case SDL_JOYDEVICEADDED:
|
||||||
|
inputHandler.handleJoystickArrivalEvent(&event.jdevice);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"SDL_WaitEvent() failed: %s",
|
|
||||||
SDL_GetError());
|
|
||||||
|
|
||||||
DispatchDeferredCleanup:
|
DispatchDeferredCleanup:
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
// HACK: See comment above
|
// HACK: See comment above
|
||||||
|
|||||||
Reference in New Issue
Block a user