From 855445983d3810a06dc836c72ff483161af3cb4e Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 22 Oct 2025 09:29:57 -0400 Subject: [PATCH] android: Add UI setting for experimental features (#40054) These commits add a new settings screen to the app, then add: 1) a setting to disable a developer-targeted UI element (an indicator about whether the app is polling continuously for events) 2) a toggle for experimental web platform features The page needs to be reloaded after switching the toggle before any changes can be observed. Testing: Manually tested by visiting https://developer.mozilla.org with the setting enabled and disabled. No automated testing for Android yet. Fixes: #39791 --------- Signed-off-by: Josh Matthews --- ports/servoshell/egl/android.rs | 30 +++++++++-- support/android/apk/servoapp/build.gradle.kts | 1 + .../apk/servoapp/src/main/AndroidManifest.xml | 5 ++ .../org/servo/servoshell/MainActivity.java | 50 +++++++++++++++++- .../servo/servoshell/SettingsActivity.java | 22 ++++++++ .../servo/servoshell/SettingsFragment.java | 14 +++++ .../servoapp/src/main/res/drawable/kebab.png | Bin 0 -> 6113 bytes .../src/main/res/layout/activity_main.xml | 12 +++++ .../src/main/res/layout/activity_settings.xml | 16 ++++++ .../servoapp/src/main/res/xml/preferences.xml | 15 ++++++ .../java/org/servo/servoview/JNIServo.java | 3 ++ .../main/java/org/servo/servoview/Servo.java | 4 ++ .../java/org/servo/servoview/ServoView.java | 11 +++- 13 files changed, 177 insertions(+), 6 deletions(-) create mode 100644 support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsActivity.java create mode 100644 support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsFragment.java create mode 100644 support/android/apk/servoapp/src/main/res/drawable/kebab.png create mode 100644 support/android/apk/servoapp/src/main/res/layout/activity_settings.xml create mode 100644 support/android/apk/servoapp/src/main/res/xml/preferences.xml diff --git a/ports/servoshell/egl/android.rs b/ports/servoshell/egl/android.rs index dd68ce8d8d8..fe501dc4865 100644 --- a/ports/servoshell/egl/android.rs +++ b/ports/servoshell/egl/android.rs @@ -22,12 +22,13 @@ use raw_window_handle::{ }; use servo::{ AlertResponse, EventLoopWaker, LoadStatus, MediaSessionActionType, MouseButton, - PermissionRequest, SimpleDialog, WebView, + PermissionRequest, PrefValue, SimpleDialog, WebView, }; use simpleservo::{APP, DeviceIntRect, InitOptions, InputMethodType, MediaSessionPlaybackState}; use super::app_state::{Coordinates, RunningAppState}; use super::host_trait::HostTrait; +use crate::prefs::EXPERIMENTAL_PREFS; struct HostCallbacks { callbacks: GlobalRef, @@ -147,6 +148,20 @@ pub extern "C" fn Java_org_servo_servoview_JNIServo_init<'local>( }; } +#[unsafe(no_mangle)] +pub extern "C" fn Java_org_servo_servoview_JNIServo_setExperimentalMode<'local>( + mut env: JNIEnv<'local>, + _class: JClass<'local>, + enable: jboolean, +) { + debug!("setExperimentalMode {enable}"); + call(&mut env, |s| { + for pref in EXPERIMENTAL_PREFS { + s.servo().set_preference(pref, PrefValue::Bool(enable != 0)); + } + }); +} + #[unsafe(no_mangle)] pub extern "C" fn Java_org_servo_servoview_JNIServo_requestShutdown<'local>( mut env: JNIEnv<'local>, @@ -853,6 +868,9 @@ fn get_options<'local>( let url = get_field_as_string(env, opts, "url")?; let log_str = get_field_as_string(env, opts, "logStr")?; let gst_debug_str = get_field_as_string(env, opts, "gstDebugStr")?; + let experimental_mode = get_non_null_field(env, opts, "experimentalMode", "Z")? + .z() + .map_err(|_| "experimentalMode not a boolean")?; let density = get_non_null_field(env, opts, "density", "F")? .f() .map_err(|_| "density not a float")? as f32; @@ -869,15 +887,19 @@ fn get_options<'local>( .map_err(|_| "coordinates is not an object")?; let coordinates = jni_coords_to_rust_coords(env, &coordinates)?; - let args = match args { + let mut args: Vec = match args { Some(args) => serde_json::from_str(&args) .map_err(|_| "Invalid arguments. Servo arguments must be formatted as a JSON array")?, None => None, - }; + } + .unwrap_or_default(); + if experimental_mode { + args.push("--enable-experimental-web-platform-features".to_owned()); + } let (display_handle, window_handle) = display_and_window_handle(env, surface); let opts = InitOptions { - args: args.unwrap_or(vec![]), + args, url, coordinates, density, diff --git a/support/android/apk/servoapp/build.gradle.kts b/support/android/apk/servoapp/build.gradle.kts index 269225dfa86..4eac28b2657 100644 --- a/support/android/apk/servoapp/build.gradle.kts +++ b/support/android/apk/servoapp/build.gradle.kts @@ -172,4 +172,5 @@ dependencies { implementation("androidx.appcompat:appcompat:1.6.1") implementation("com.google.android.material:material:1.9.0") implementation("androidx.constraintlayout:constraintlayout:2.1.3") + implementation("androidx.preference:preference-ktx:1.2.0") } diff --git a/support/android/apk/servoapp/src/main/AndroidManifest.xml b/support/android/apk/servoapp/src/main/AndroidManifest.xml index 2264ea4f7a3..4e2809da52d 100644 --- a/support/android/apk/servoapp/src/main/AndroidManifest.xml +++ b/support/android/apk/servoapp/src/main/AndroidManifest.xml @@ -43,6 +43,11 @@ + + diff --git a/support/android/apk/servoapp/src/main/java/org/servo/servoshell/MainActivity.java b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/MainActivity.java index 30c70207c0e..c63a66b9f03 100644 --- a/support/android/apk/servoapp/src/main/java/org/servo/servoshell/MainActivity.java +++ b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/MainActivity.java @@ -9,8 +9,10 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; import android.system.ErrnoException; import android.system.Os; import android.util.Log; @@ -45,6 +47,17 @@ public class MainActivity extends Activity implements Servo.Client { boolean mCanGoBack; MediaSession mMediaSession; + class Settings { + Settings(SharedPreferences preferences) { + showAnimatingIndicator = preferences.getBoolean("animating_indicator", false); + experimental = preferences.getBoolean("experimental", false); + } + + boolean showAnimatingIndicator; + boolean experimental; + } + Settings mSettings; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -61,6 +74,8 @@ public class MainActivity extends Activity implements Servo.Client { mIdleText = findViewById(R.id.redrawing); mCanGoBack = false; + updateSettingsIfNecessary(true); + mBackButton.setEnabled(false); mFwdButton.setEnabled(false); @@ -82,7 +97,7 @@ public class MainActivity extends Activity implements Servo.Client { Intent intent = getIntent(); String args = intent.getStringExtra("servoargs"); String log = intent.getStringExtra("servolog"); - mServoView.setServoArgs(args, log); + mServoView.setServoArgs(args, log, mSettings.experimental); if (Intent.ACTION_VIEW.equals(intent.getAction())) { mServoView.loadUri(intent.getData().toString()); @@ -126,6 +141,11 @@ public class MainActivity extends Activity implements Servo.Client { } // From activity_main.xml: + public void onSettingsClicked(View v) { + Intent myIntent = new Intent(this, SettingsActivity.class); + startActivity(myIntent); + } + public void onReloadClicked(View v) { mServoView.reload(); } @@ -243,6 +263,7 @@ public class MainActivity extends Activity implements Servo.Client { public void onResume() { mServoView.onResume(); super.onResume(); + updateSettingsIfNecessary(false); } @Override @@ -291,4 +312,31 @@ public class MainActivity extends Activity implements Servo.Client { mMediaSession.setPositionState(duration, position, playbackRate); } + + public void onAnimatingIndicatorPrefChanged(boolean value) { + if (value) { + mIdleText.setVisibility(View.VISIBLE); + } else { + mIdleText.setVisibility(View.GONE); + } + } + + public void onExperimentalPrefChanged(boolean value) { + mServoView.setExperimentalMode(value); + } + + public void updateSettingsIfNecessary(boolean force) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + Settings updated = new Settings(preferences); + + if (force || updated.showAnimatingIndicator != mSettings.showAnimatingIndicator) { + onAnimatingIndicatorPrefChanged(updated.showAnimatingIndicator); + } + + if (force || updated.experimental != mSettings.experimental) { + onExperimentalPrefChanged(updated.experimental); + } + + mSettings = updated; + } } diff --git a/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsActivity.java b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsActivity.java new file mode 100644 index 00000000000..128c2a44b08 --- /dev/null +++ b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsActivity.java @@ -0,0 +1,22 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.servo.servoshell; + +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; + +public class SettingsActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings_container, new SettingsFragment()) + .commit(); + } +} diff --git a/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsFragment.java b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsFragment.java new file mode 100644 index 00000000000..e4ce20277c5 --- /dev/null +++ b/support/android/apk/servoapp/src/main/java/org/servo/servoshell/SettingsFragment.java @@ -0,0 +1,14 @@ +package org.servo.servoshell; + +import android.os.Bundle; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.SwitchPreferenceCompat; + +public class SettingsFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.preferences, rootKey); + + SwitchPreferenceCompat animatingPref = findPreference("animating_indicator"); + } +} diff --git a/support/android/apk/servoapp/src/main/res/drawable/kebab.png b/support/android/apk/servoapp/src/main/res/drawable/kebab.png new file mode 100644 index 0000000000000000000000000000000000000000..5a8bc8fecf8932c9b4f5da26ce59be1194903304 GIT binary patch literal 6113 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 + + + diff --git a/support/android/apk/servoapp/src/main/res/layout/activity_settings.xml b/support/android/apk/servoapp/src/main/res/layout/activity_settings.xml new file mode 100644 index 00000000000..ff0133a977c --- /dev/null +++ b/support/android/apk/servoapp/src/main/res/layout/activity_settings.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/support/android/apk/servoapp/src/main/res/xml/preferences.xml b/support/android/apk/servoapp/src/main/res/xml/preferences.xml new file mode 100644 index 00000000000..543d634d539 --- /dev/null +++ b/support/android/apk/servoapp/src/main/res/xml/preferences.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java index ae8fadc81d3..464f50dea80 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java @@ -67,6 +67,8 @@ public class JNIServo { public native void mediaSessionAction(int action); + public native void setExperimentalMode(boolean enable); + public static class ServoOptions { public String args; public String url; @@ -77,6 +79,7 @@ public class JNIServo { public String logStr; public String gstDebugStr; public boolean enableLogs = false; + public boolean experimentalMode = false; } public static class ServoCoordinates { diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java index 7e78d82a456..fcb161d567c 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java @@ -167,6 +167,10 @@ public class Servo { mRunCallback.inGLThread(() -> mJNI.mediaSessionAction(action)); } + public void setExperimentalMode(boolean enable) { + mRunCallback.inGLThread(() -> mJNI.setExperimentalMode(enable)); + } + public interface Client { void onAlert(String message); diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java index e0327ddcf83..ca624db2fe3 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java @@ -59,6 +59,7 @@ public class ServoView extends SurfaceView private ScaleGestureDetector mScaleGestureDetector; private OverScroller mScroller; + private boolean mExperimentalMode; private boolean mZooming; private float mZoomFactor = 1; private boolean mRedrawing; @@ -95,9 +96,10 @@ public class ServoView extends SurfaceView mClient = client; } - public void setServoArgs(String args, String log) { + public void setServoArgs(String args, String log, boolean experimentalMode) { mServoArgs = args; mServoLog = log; + mExperimentalMode = experimentalMode; } // RunCallback @@ -362,6 +364,12 @@ public class ServoView extends SurfaceView mServo.mediaSessionAction(action); } + public void setExperimentalMode(boolean enable) { + if (mServo != null) { + mServo.setExperimentalMode(enable); + } + } + class GLThread extends Thread implements SurfaceHolder.Callback { private Activity mActivity; private ServoView mServoView; @@ -384,6 +392,7 @@ public class ServoView extends SurfaceView options.coordinates = coords; options.enableLogs = true; options.enableSubpixelTextAntialiasing = true; + options.experimentalMode = mServoView.mExperimentalMode; DisplayMetrics metrics = new DisplayMetrics(); mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);