mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-10 13:44:17 +00:00
Add support for listing notch and notchless native resolution options
This commit is contained in:
parent
ed68f920f1
commit
85a9f85c54
6 changed files with 88 additions and 33 deletions
|
@ -74,6 +74,7 @@ SystemProperties::SystemProperties()
|
||||||
|
|
||||||
Q_ASSERT(!monitorRefreshRates.isEmpty());
|
Q_ASSERT(!monitorRefreshRates.isEmpty());
|
||||||
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
||||||
|
Q_ASSERT(!monitorSafeAreaResolutions.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect SystemProperties::getNativeResolution(int displayIndex)
|
QRect SystemProperties::getNativeResolution(int displayIndex)
|
||||||
|
@ -82,6 +83,12 @@ QRect SystemProperties::getNativeResolution(int displayIndex)
|
||||||
return monitorNativeResolutions.value(displayIndex);
|
return monitorNativeResolutions.value(displayIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect SystemProperties::getSafeAreaResolution(int displayIndex)
|
||||||
|
{
|
||||||
|
// Returns default constructed QRect if out of bounds
|
||||||
|
return monitorSafeAreaResolutions.value(displayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
int SystemProperties::getRefreshRate(int displayIndex)
|
int SystemProperties::getRefreshRate(int displayIndex)
|
||||||
{
|
{
|
||||||
// Returns 0 if out of bounds
|
// Returns 0 if out of bounds
|
||||||
|
@ -199,10 +206,12 @@ void SystemProperties::refreshDisplaysInternal()
|
||||||
SDL_DisplayMode bestMode;
|
SDL_DisplayMode bestMode;
|
||||||
for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) {
|
for (int displayIndex = 0; displayIndex < SDL_GetNumVideoDisplays(); displayIndex++) {
|
||||||
SDL_DisplayMode desktopMode;
|
SDL_DisplayMode desktopMode;
|
||||||
|
SDL_Rect safeArea;
|
||||||
|
|
||||||
if (StreamUtils::getNativeDesktopMode(displayIndex, &desktopMode)) {
|
if (StreamUtils::getNativeDesktopMode(displayIndex, &desktopMode, &safeArea)) {
|
||||||
if (desktopMode.w <= 8192 && desktopMode.h <= 8192) {
|
if (desktopMode.w <= 8192 && desktopMode.h <= 8192) {
|
||||||
monitorNativeResolutions.insert(displayIndex, QRect(0, 0, desktopMode.w, desktopMode.h));
|
monitorNativeResolutions.insert(displayIndex, QRect(0, 0, desktopMode.w, desktopMode.h));
|
||||||
|
monitorSafeAreaResolutions.insert(displayIndex, QRect(0, 0, safeArea.w, safeArea.h));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void refreshDisplays();
|
Q_INVOKABLE void refreshDisplays();
|
||||||
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
||||||
|
Q_INVOKABLE QRect getSafeAreaResolution(int displayIndex);
|
||||||
Q_INVOKABLE int getRefreshRate(int displayIndex);
|
Q_INVOKABLE int getRefreshRate(int displayIndex);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -52,6 +53,7 @@ private:
|
||||||
QString unmappedGamepads;
|
QString unmappedGamepads;
|
||||||
QSize maximumResolution;
|
QSize maximumResolution;
|
||||||
QList<QRect> monitorNativeResolutions;
|
QList<QRect> monitorNativeResolutions;
|
||||||
|
QList<QRect> monitorSafeAreaResolutions;
|
||||||
QList<int> monitorRefreshRates;
|
QList<int> monitorRefreshRates;
|
||||||
QString versionString;
|
QString versionString;
|
||||||
bool supportsHdr;
|
bool supportsHdr;
|
||||||
|
|
|
@ -133,33 +133,18 @@ Flickable {
|
||||||
AutoResizingComboBox {
|
AutoResizingComboBox {
|
||||||
property int lastIndexValue
|
property int lastIndexValue
|
||||||
|
|
||||||
// ignore setting the index at first, and actually set it when the component is loaded
|
function addDetectedResolution(friendlyNamePrefix, rect) {
|
||||||
Component.onCompleted: {
|
|
||||||
// Refresh display data before using it to build the list
|
|
||||||
SystemProperties.refreshDisplays()
|
|
||||||
|
|
||||||
// Add native resolutions for all attached displays
|
|
||||||
var done = false
|
|
||||||
for (var displayIndex = 0; !done; displayIndex++) {
|
|
||||||
var screenRect = SystemProperties.getNativeResolution(displayIndex);
|
|
||||||
|
|
||||||
if (screenRect.width === 0) {
|
|
||||||
// Exceeded max count of displays
|
|
||||||
done = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexToAdd = 0
|
var indexToAdd = 0
|
||||||
for (var j = 0; j < resolutionComboBox.count; j++) {
|
for (var j = 0; j < resolutionComboBox.count; j++) {
|
||||||
var existing_width = parseInt(resolutionListModel.get(j).video_width);
|
var existing_width = parseInt(resolutionListModel.get(j).video_width);
|
||||||
var existing_height = parseInt(resolutionListModel.get(j).video_height);
|
var existing_height = parseInt(resolutionListModel.get(j).video_height);
|
||||||
|
|
||||||
if (screenRect.width === existing_width && screenRect.height === existing_height) {
|
if (rect.width === existing_width && rect.height === existing_height) {
|
||||||
// Duplicate entry, skip
|
// Duplicate entry, skip
|
||||||
indexToAdd = -1
|
indexToAdd = -1
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
else if (screenRect.width * screenRect.height > existing_width * existing_height) {
|
else if (rect.width * rect.height > existing_width * existing_height) {
|
||||||
// Candidate entrypoint after this entry
|
// Candidate entrypoint after this entry
|
||||||
indexToAdd = j + 1
|
indexToAdd = j + 1
|
||||||
}
|
}
|
||||||
|
@ -169,14 +154,35 @@ Flickable {
|
||||||
if (indexToAdd >= 0) {
|
if (indexToAdd >= 0) {
|
||||||
resolutionListModel.insert(indexToAdd,
|
resolutionListModel.insert(indexToAdd,
|
||||||
{
|
{
|
||||||
"text": "Native ("+screenRect.width+"x"+screenRect.height+")",
|
"text": friendlyNamePrefix+" ("+rect.width+"x"+rect.height+")",
|
||||||
"video_width": ""+screenRect.width,
|
"video_width": ""+rect.width,
|
||||||
"video_height": ""+screenRect.height,
|
"video_height": ""+rect.height,
|
||||||
"is_custom": false
|
"is_custom": false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore setting the index at first, and actually set it when the component is loaded
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Refresh display data before using it to build the list
|
||||||
|
SystemProperties.refreshDisplays()
|
||||||
|
|
||||||
|
// Add native and safe area resolutions for all attached displays
|
||||||
|
var done = false
|
||||||
|
for (var displayIndex = 0; !done; displayIndex++) {
|
||||||
|
var screenRect = SystemProperties.getNativeResolution(displayIndex);
|
||||||
|
var safeAreaRect = SystemProperties.getSafeAreaResolution(displayIndex);
|
||||||
|
|
||||||
|
if (screenRect.width === 0) {
|
||||||
|
// Exceeded max count of displays
|
||||||
|
done = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
addDetectedResolution(qsTr("Native"), screenRect)
|
||||||
|
addDetectedResolution(qsTr("Native (Excluding Notch)"), safeAreaRect)
|
||||||
|
}
|
||||||
|
|
||||||
// Prune resolutions that are over the decoder's maximum
|
// Prune resolutions that are over the decoder's maximum
|
||||||
var max_pixels = SystemProperties.maximumResolution.width * SystemProperties.maximumResolution.height;
|
var max_pixels = SystemProperties.maximumResolution.width * SystemProperties.maximumResolution.height;
|
||||||
if (max_pixels > 0) {
|
if (max_pixels > 0) {
|
||||||
|
@ -210,7 +216,7 @@ Flickable {
|
||||||
if (!index_set) {
|
if (!index_set) {
|
||||||
// We did not find a match. This must be a custom resolution.
|
// We did not find a match. This must be a custom resolution.
|
||||||
resolutionListModel.append({
|
resolutionListModel.append({
|
||||||
"text": "Custom ("+StreamingPreferences.width+"x"+StreamingPreferences.height+")",
|
"text": qsTr("Custom")+" ("+StreamingPreferences.width+"x"+StreamingPreferences.height+")",
|
||||||
"video_width": ""+StreamingPreferences.width,
|
"video_width": ""+StreamingPreferences.width,
|
||||||
"video_height": ""+StreamingPreferences.height,
|
"video_height": ""+StreamingPreferences.height,
|
||||||
"is_custom": true
|
"is_custom": true
|
||||||
|
@ -219,7 +225,7 @@ Flickable {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolutionListModel.append({
|
resolutionListModel.append({
|
||||||
"text": "Custom",
|
"text": qsTr("Custom"),
|
||||||
"video_width": "",
|
"video_width": "",
|
||||||
"video_height": "",
|
"video_height": "",
|
||||||
"is_custom": true
|
"is_custom": true
|
||||||
|
|
|
@ -1200,7 +1200,8 @@ void Session::updateOptimalWindowDisplayMode()
|
||||||
// If this doesn't fit the selected resolution, use the native
|
// If this doesn't fit the selected resolution, use the native
|
||||||
// resolution of the panel (unscaled).
|
// resolution of the panel (unscaled).
|
||||||
if (desktopMode.w < m_ActiveVideoWidth || desktopMode.h < m_ActiveVideoHeight) {
|
if (desktopMode.w < m_ActiveVideoWidth || desktopMode.h < m_ActiveVideoHeight) {
|
||||||
if (!StreamUtils::getNativeDesktopMode(displayIndex, &desktopMode)) {
|
SDL_Rect safeArea;
|
||||||
|
if (!StreamUtils::getNativeDesktopMode(displayIndex, &desktopMode, &safeArea)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ bool StreamUtils::hasFastAes()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode)
|
bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode, SDL_Rect* safeArea)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_DARWIN
|
#ifdef Q_OS_DARWIN
|
||||||
#define MAX_DISPLAYS 16
|
#define MAX_DISPLAYS 16
|
||||||
|
@ -223,6 +223,37 @@ bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
safeArea->x = 0;
|
||||||
|
safeArea->y = 0;
|
||||||
|
safeArea->w = mode->w;
|
||||||
|
safeArea->h = mode->h;
|
||||||
|
|
||||||
|
#if TARGET_CPU_ARM64
|
||||||
|
// Now that we found the native full-screen mode, let's look for one that matches along
|
||||||
|
// the width but not the height and we'll assume that's the safe area full-screen mode.
|
||||||
|
//
|
||||||
|
// There doesn't appear to be a CG API or flag that will tell us that a given mode
|
||||||
|
// is a "safe area" mode, so we have to use our own (brittle) heuristics. :(
|
||||||
|
//
|
||||||
|
// To avoid potential false positives, let's avoid checking for external displays, since
|
||||||
|
// we might have scenarios like a 1920x1200 display with an alternate 1920x1080 mode
|
||||||
|
// which would falsely trigger our notch detection here.
|
||||||
|
if (CGDisplayIsBuiltin(displayIds[displayIndex])) {
|
||||||
|
for (CFIndex i = 0; i < count; i++) {
|
||||||
|
auto cgMode = (CGDisplayModeRef)(CFArrayGetValueAtIndex(modeList, i));
|
||||||
|
auto cgModeWidth = static_cast<int>(CGDisplayModeGetWidth(cgMode));
|
||||||
|
auto cgModeHeight = static_cast<int>(CGDisplayModeGetHeight(cgMode));
|
||||||
|
|
||||||
|
// If the modes differ by more than 100, we'll assume it's not a notch mode
|
||||||
|
if (mode->w == cgModeWidth && mode->h != cgModeHeight && mode->h <= cgModeHeight + 100) {
|
||||||
|
safeArea->w = cgModeWidth;
|
||||||
|
safeArea->h = cgModeHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CFRelease(modeList);
|
CFRelease(modeList);
|
||||||
|
|
||||||
// Now find the SDL mode that matches the CG native mode
|
// Now find the SDL mode that matches the CG native mode
|
||||||
|
@ -258,7 +289,13 @@ bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
safeArea->x = 0;
|
||||||
|
safeArea->y = 0;
|
||||||
|
safeArea->w = mode->w;
|
||||||
|
safeArea->h = mode->h;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
void screenSpaceToNormalizedDeviceCoords(SDL_Rect* src, SDL_FRect* dst, int viewportWidth, int viewportHeight);
|
void screenSpaceToNormalizedDeviceCoords(SDL_Rect* src, SDL_FRect* dst, int viewportWidth, int viewportHeight);
|
||||||
|
|
||||||
static
|
static
|
||||||
bool getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode);
|
bool getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode, SDL_Rect* safeArea);
|
||||||
|
|
||||||
static
|
static
|
||||||
int getDisplayRefreshRate(SDL_Window* window);
|
int getDisplayRefreshRate(SDL_Window* window);
|
||||||
|
|
Loading…
Reference in a new issue