fix: persist SDL3 controller settings

This commit is contained in:
XxJSONDeruloxX committed 2026-10-25 11:15:46 -04:00
1 parent 497b92e63d
commit efc335673d
5 files changed
+67 -1

No files matched your search

@@ -4,10 +4,15 @@ import android.app.Application
import android.content.ComponentName
import android.content.ContextWrapper
import android.content.pm.PackageManager
import android.view.KeyEvent
import android.widget.LinearLayout
import android.widget.SeekBar
import java.lang.reflect.Proxy
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.Before
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
@@ -17,6 +22,32 @@ import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28], application = Application::class)
class EmbeddedBridgeTest {
@Before fun resetSettings() {
Settings::class.java.getDeclaredField("prefs").apply { isAccessible = true }.set(null, null)
}
@Test
fun keyboardSliderChangesAreSavedWithoutATouchDrag() {
val app = RuntimeEnvironment.getApplication()
Settings.init(app)
val activity = Robolectric.buildActivity(BridgeActivity::class.java).get()
val root = LinearLayout(activity)
val sinkType = BridgeActivity::class.java.declaredClasses.single { it.simpleName == "IntSink" }
val sink = Proxy.newProxyInstance(sinkType.classLoader, arrayOf(sinkType)) { _, method, args ->
if (method.name == "set") Settings.gyroGain[1] = args[0] as Int
null
}
Settings.gyroGain[1] = 100
BridgeActivity::class.java.declaredMethods.single { it.name == "addSlider" }
.apply { isAccessible = true }.invoke(activity, root, "Gyro speed", 800, 100, sink)
val slider = root.getChildAt(1) as SeekBar
assertTrue(slider.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT)))
assertTrue(slider.progress > 100)
assertEquals(slider.progress, app.getSharedPreferences(Host.prefs(app, "bridge"), 0)
.getInt("gyroGain_p1", -1))
}
@Test
fun calibrationUsesOnlyTheSelectedPlayer() {
Settings.init(RuntimeEnvironment.getApplication())
@@ -0,0 +1,23 @@
--- a/java/com/example/dsedge/BridgeActivity.java
+++ b/java/com/example/dsedge/BridgeActivity.java
@@ -454,12 +454,16 @@
sb.setProgressTintList(ColorStateList.valueOf(ACCENT));
sb.setThumbTintList(ColorStateList.valueOf(ACCENT));
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ private boolean tracking;
@Override public void onProgressChanged(SeekBar s, int v, boolean fromUser) {
t.setText(label + ": " + v);
- if (fromUser) sink.set(v);
- }
- @Override public void onStartTrackingTouch(SeekBar s) { }
- @Override public void onStopTrackingTouch(SeekBar s) { Settings.save(); }
+ if (fromUser) {
+ sink.set(v);
+ if (!tracking) Settings.save();
+ }
+ }
+ @Override public void onStartTrackingTouch(SeekBar s) { tracking = true; }
+ @Override public void onStopTrackingTouch(SeekBar s) { tracking = false; Settings.save(); }
});
root.addView(t);
root.addView(sb);
+2 -1
View File
@@ -70,6 +70,7 @@
},
"patches": [
"patches/0001-droiddeck-integration.patch",
"patches/0002-controller-state-fixes.patch"
"patches/0002-controller-state-fixes.patch",
"patches/0003-persist-controller-settings.patch"
]
}
+1
View File
@@ -23,6 +23,7 @@ def prepare(root=ROOT, output=None):
output = output or build / 'controller-sources'
if output.is_symlink() or output.resolve() == build.resolve() or not output.resolve().is_relative_to(build.resolve()):
raise ValueError('Controller sources must be generated below app/build')
output = output.resolve()
output.parent.mkdir(parents=True, exist_ok=True)
with tempfile.TemporaryDirectory(prefix='controller-sources-', dir=output.parent) as temporary:
stage = Path(temporary)
+10
View File
@@ -1,6 +1,7 @@
import difflib
import hashlib
import json
import os
from pathlib import Path
import tempfile
import unittest
@@ -42,6 +43,15 @@ class ControllerSourcesTest(unittest.TestCase):
prepare(self.root)
self.assertEqual('keep', (output / 'previous').read_text())
def test_accepts_a_relative_output_path(self):
previous = Path.cwd()
try:
os.chdir(self.root)
prepare(self.root, Path('app/build/relative'))
finally:
os.chdir(previous)
self.assertEqual(b'embedded\n', (self.root / 'app/build/relative/sdlbridge/java/Input.java').read_bytes())
def test_fails_when_an_upstream_update_breaks_a_patch(self):
vendor = self.root / 'third_party/sdlbridge'
(vendor / 'upstream/java/Input.java').write_bytes(b'new upstream\n')