moonlight-stream / moonlight-android

GameStream client for Android
GNU General Public License v3.0
4.28k stars 681 forks source link

Request for Custom Resolution Feature #1326

Open 3837262 opened 9 months ago

3837262 commented 9 months ago

Is your feature request related to a problem? Please describe.

The host resolution and the video resolution do not match, causing inconvenience. I want to add a custom resolution feature to solve this.

Describe the solution you'd like

I would like to add a feature that allows users to set their own resolution. For this, I have added code inside the onCreate method in the StreamSettings.java file.


// Load the saved resolution.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String customResolution = prefs.getString("custom_resolution", "1280x720");

// Convert the loaded resolution to the "Custom(resolution)" format.
String displayResolution = "Custom(" + customResolution + ")";

// Add the converted resolution to the resolution list.
ListPreference listPreference = (ListPreference) findPreference("list_resolution");
CharSequence[] entries = listPreference.getEntries();
CharSequence[] newEntries = new CharSequence[entries.length + 1];
System.arraycopy(entries, 0, newEntries, 0, entries.length);
newEntries[entries.length] = displayResolution;
listPreference.setEntries(newEntries);

// Add the loaded resolution to the resolution value list.
CharSequence[] entryValues = listPreference.getEntryValues();
CharSequence[] newEntryValues = new CharSequence[entryValues.length + 1];
System.arraycopy(entryValues, 0, newEntryValues, 0, entryValues.length);
newEntryValues[entryValues.length] = customResolution; // The actual resolution value is the part excluding "Custom()".
listPreference.setEntryValues(newEntryValues);

// Find the EditTextPreference that saves and loads the resolution entered by the user.
EditTextPreference editTextPreference = (EditTextPreference) findPreference("custom_resolution");
editTextPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        // Resolution input validation
        if (!Pattern.matches("\\d+x\\d+", newValue.toString())) {
            Toast.makeText(getActivity(), "Invalid format. Please enter resolution in WIDTHxHEIGHT format.", Toast.LENGTH_SHORT).show();
            return false;
        }

        // Save the resolution entered by the user as it is.
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString("custom_resolution", newValue.toString());
        editor.apply();

        // Load the saved resolution.
        String customResolution = prefs.getString("custom_resolution", "1280x720");

        // Convert the loaded resolution to the "Custom(resolution)" format.
        String displayResolution = "Custom(" + customResolution + ")";

        // Add the converted resolution to the resolution list.
        CharSequence[] newEntries = new CharSequence[entries.length + 1];
        System.arraycopy(entries, 0, newEntries, 0, entries.length);
        newEntries[entries.length] = displayResolution;
        listPreference.setEntries(newEntries);

        // Add the loaded resolution to the resolution value list.
        CharSequence[] newEntryValues = new CharSequence[entryValues.length + 1];
        System.arraycopy(entryValues, 0, newEntryValues, 0, entryValues.length);
        newEntryValues[entryValues.length] = newValue.toString(); // The actual resolution value is the part excluding "Custom()".
        listPreference.setEntryValues(newEntryValues);

        return true;
    }
});

In addition to the above, I also made modifications to the preferences.xml file as follows:


<EditTextPreference
    android:key="custom_resolution"
    android:title="Custom Resolution"
    android:summary="Enter a resolution in the format WIDTHxHEIGHT (e.g., 1280x720)"
    android:inputType="text"
    android:digits="0123456789x"
    android:dialogTitle="Enter a custom resolution" />

Describe alternatives you've considered

No specific alternatives have been considered.

Screenshots

Additional context: When using this code, a native resolution warning may appear when selecting a resolution from the user-defined resolution list. However, it seems that there is no problem with use even when the warning appears. This code was written using Microsoft’s Copilot, despite having no prior knowledge of coding or Android Studio. Screenshot_20240209_111603_Moonlight (Debug) Screenshot_20240209_111526_Moonlight (Debug) Screenshot_20240209_111557_Moonlight (Debug) Screenshot_20240209_112122_Moonlight (Debug)

pengxiao1991 commented 8 months ago

@3837262 good job,and i want this apk, can i?

MaurilhoB commented 8 months ago

@pengxiao1991 I was also needing this feature so I made a fork and implemented it by myself for my personal use, if you want you can get the apk in my fork releases page here

SouljaVR commented 7 months ago

@pengxiao1991 I was also needing this feature so I made a fork and implemented it by myself for my personal use, if you want you can get the apk in my fork releases page here

Thank you so much - Don't know why this isn't already a feature by now

kajdo commented 6 months ago

I would love to see this feature. My usecase isn't gaming, but remote connect to my hyprland main pc using a galaxy tab s7fe.

since the tablet has a 16x10 display, I'm always bothered by the black bars. My workaround is to set the host resolution to 1680x1050 and the moonlight client to "native" which is 2560x1600.

this way the 16x10 resolution works out without black bars, but since moonlight asks sunshine for a much higher resolution the latency is higher than connecting with 1920x1080 (even with the host still being in 1680x1050).

stretch to fullscreen doesn't help either.

I know that there was a guy on xda-developers who did some custom-resolutions and released an alternative apk, but a native supported implementation would be so much better because it doesn't need a seperate maintainer.

@3837262 thx for the work!!

@MaurilhoB thx - i will also give it a shot

AbbieDoobie commented 4 months ago

I tried that custom build, hoping I could work around a wonky issue with getting proper 4k on an Nvidia Shield while all display modes are enabled (https://github.com/moonlight-stream/moonlight-android/issues/1303)

I entered "3840x2160" as a custom resolution in the build, but it did not appear as an option. "3841x2160" did appear, but obviously did not work.

Is there a way to bypass whatever Moonlight Android is trying to auto-detect with resolutions and just force a specific one full stop? This problem is downright infuriating D: