diff options
| author | Lena <lena@omega> | 2026-08-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-08-01 00:00:00 +0000 |
| commit | 852a8a00273c9128efeed0217a8e5d3fcd8bf780 (patch) | |
| tree | c72f959731fa3c7c809cf1a0222363b6c9c9b03b /app/src/main/res/layout | |
| parent | f379b93d52bf0dbd3816ec3f64d165314771d2a6 (diff) | |
| download | scrcpy-android-852a8a00273c9128efeed0217a8e5d3fcd8bf780.tar.gz | |
app: harden mirroring lifecycle and state
Diffstat (limited to 'app/src/main/res/layout')
| -rw-r--r-- | app/src/main/res/layout/device_row.xml | 28 | ||||
| -rw-r--r-- | app/src/main/res/layout/licenses.xml | 20 | ||||
| -rw-r--r-- | app/src/main/res/layout/main.xml | 264 | ||||
| -rw-r--r-- | app/src/main/res/layout/mirror.xml | 46 | ||||
| -rw-r--r-- | app/src/main/res/layout/settings.xml | 60 |
5 files changed, 242 insertions, 176 deletions
diff --git a/app/src/main/res/layout/device_row.xml b/app/src/main/res/layout/device_row.xml index f06ab20..0471639 100644 --- a/app/src/main/res/layout/device_row.xml +++ b/app/src/main/res/layout/device_row.xml @@ -1,28 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Saved-device row: phone glyph + "host:port" label, with the platform - touch ripple. Bound by an ArrayAdapter via R.id.device_label. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<!-- Saved-device row with a platform touch ripple. --> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/device_label" + style="@style/DeviceLabel" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" android:gravity="center_vertical" android:minHeight="56dp" android:paddingHorizontal="@dimen/space_sm" android:paddingVertical="@dimen/space_md" - android:background="?android:attr/selectableItemBackground"> - - <ImageView - android:layout_width="24dp" - android:layout_height="24dp" - android:src="@drawable/ic_device" - android:contentDescription="@null"/> - - <TextView - android:id="@+id/device_label" - style="@style/DeviceLabel" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginStart="@dimen/space_md"/> - -</LinearLayout> + android:drawableStart="@drawable/ic_device" + android:drawablePadding="@dimen/space_md" + android:foreground="?android:attr/selectableItemBackground"/> diff --git a/app/src/main/res/layout/licenses.xml b/app/src/main/res/layout/licenses.xml new file mode 100644 index 0000000..6ca02ab --- /dev/null +++ b/app/src/main/res/layout/licenses.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Plain scrolling text. The notices are wrapped at 78 columns in the + asset, so they are shown in a monospace face at a size that does not + re-wrap them into nonsense. --> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/root" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="@dimen/space_lg"> + + <TextView + android:id="@+id/notices" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@color/on_surface" + android:textSize="12sp" + android:fontFamily="monospace" + android:textIsSelectable="true"/> + +</ScrollView> diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index 0b1273b..15b1c90 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -1,161 +1,177 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Root padding is the base; Ui.padForInsets() adds the system bar and +<!-- One scroll for the whole page. The saved-device rows are built into + the LinearLayout below rather than a ListView, because a ListView + inside a ScrollView cannot measure itself and splitting the screen + into two independently scrolling halves left one of them unusable at + some sizes. The list is a handful of rows; it does not need + recycling. + + Root padding is the base; Ui.padForInsets() adds the system bar and IME insets to it at runtime (the window is edge-to-edge). --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" + android:fillViewport="true" android:padding="@dimen/space_lg"> - <!-- Header: app glyph + name, Settings on the right. --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" - android:gravity="center_vertical" - android:layout_marginBottom="@dimen/space_lg"> + android:orientation="vertical"> - <ImageView - android:layout_width="40dp" - android:layout_height="40dp" - android:src="@drawable/ic_launcher_foreground" - android:scaleType="fitCenter" - android:contentDescription="@null"/> - - <TextView - android:layout_width="0dp" + <!-- Header: app glyph + name, Settings on the right. --> + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginStart="@dimen/space_sm" - android:text="@string/app_name" - android:textColor="@color/on_surface" - android:textSize="22sp" - android:textStyle="bold"/> - - <ImageButton - android:id="@+id/settings" - android:layout_width="48dp" - android:layout_height="48dp" - android:src="@drawable/ic_settings" - android:scaleType="centerInside" - android:background="?android:attr/selectableItemBackgroundBorderless" - android:contentDescription="@string/settings"/> - - </LinearLayout> - - <!-- Pairing form. Each field is one value the target already prints, - copied verbatim: the Wireless debugging screen shows the device - address as a single "ip:port" string, and the pairing dialog adds - its own port plus the code. --> - <LinearLayout - style="@style/Card" - android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginBottom="@dimen/space_lg"> - <TextView - style="@style/SectionHeader" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/pair_a_device"/> + <ImageView + android:layout_width="40dp" + android:layout_height="40dp" + android:src="@drawable/ic_launcher_foreground" + android:scaleType="fitCenter" + android:contentDescription="@null"/> - <TextView - style="@style/Caption" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/pair_help"/> + <TextView + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginStart="@dimen/space_sm" + android:text="@string/app_name" + android:textColor="@color/on_surface" + android:textSize="22sp" + android:textStyle="bold"/> + + <ImageButton + android:id="@+id/settings" + android:layout_width="48dp" + android:layout_height="48dp" + android:src="@drawable/ic_settings" + android:scaleType="centerInside" + android:background="?android:attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/settings"/> - <TextView - style="@style/FieldLabel" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/label_address"/> + </LinearLayout> - <TextView - style="@style/Caption" + <!-- Pairing form. Each field is one value the target already + prints, copied verbatim: the Wireless debugging screen shows + the device address as a single "ip:port" string, and the + pairing dialog adds its own port plus the code. --> + <LinearLayout + style="@style/Card" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/sub_address"/> + android:layout_height="wrap_content"> - <EditText - android:id="@+id/device_address" - style="@style/Field" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/space_xs" - android:hint="@string/address_hint" - android:inputType="textUri" - android:autofillHints="postalAddress"/> + <TextView + style="@style/SectionHeader" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/pair_a_device"/> - <TextView - style="@style/FieldLabel" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/label_pairing"/> + <TextView + style="@style/Caption" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/pair_help"/> - <TextView - style="@style/Caption" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/sub_pairing"/> + <TextView + style="@style/FieldLabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_address"/> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_marginTop="@dimen/space_xs"> + <TextView + style="@style/Caption" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sub_address"/> <EditText - android:id="@+id/pair_port" + android:id="@+id/device_address" style="@style/Field" - android:layout_width="0dp" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginEnd="@dimen/space_sm" - android:hint="@string/pair_port_hint" - android:inputType="number" - android:autofillHints="off"/> + android:layout_marginTop="@dimen/space_xs" + android:hint="@string/address_hint" + android:inputType="textUri" + android:importantForAutofill="no"/> + + <TextView + style="@style/FieldLabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_pairing"/> - <EditText - android:id="@+id/pair_code" - style="@style/Field" - android:layout_width="0dp" + <TextView + style="@style/Caption" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" - android:hint="@string/pair_code_hint" - android:inputType="numberPassword" - android:maxLength="6" - android:autofillHints="off"/> + android:text="@string/sub_pairing"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="@dimen/space_xs"> + + <EditText + android:id="@+id/pair_port" + style="@style/Field" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginEnd="@dimen/space_sm" + android:hint="@string/pair_port_hint" + android:inputType="number" + android:importantForAutofill="no"/> + + <EditText + android:id="@+id/pair_code" + style="@style/Field" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:hint="@string/pair_code_hint" + android:inputType="numberPassword" + android:maxLength="6" + android:importantForAutofill="no"/> + + </LinearLayout> + + <TextView + style="@style/Caption" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/space_md" + android:text="@string/network_trust"/> + + <Button + android:id="@+id/pair" + style="@style/Button.Primary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/space_lg" + android:text="@string/pair_and_save"/> </LinearLayout> - <Button - android:id="@+id/pair" - style="@style/Button.Primary" + <TextView + style="@style/SectionHeader" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/space_lg" - android:text="@string/pair_and_save"/> - - </LinearLayout> + android:text="@string/saved_devices"/> - <TextView - style="@style/SectionHeader" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/saved_devices"/> - - <FrameLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1"> - - <ListView + <LinearLayout android:id="@+id/devices" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" android:divider="@color/stroke" - android:dividerHeight="1dp"/> + android:showDividers="middle" + android:dividerPadding="0dp"/> <TextView android:id="@+id/devices_empty" @@ -166,6 +182,6 @@ android:paddingTop="@dimen/space_xl" android:text="@string/no_devices_yet"/> - </FrameLayout> + </LinearLayout> -</LinearLayout> +</ScrollView> diff --git a/app/src/main/res/layout/mirror.xml b/app/src/main/res/layout/mirror.xml index cf24e11..d2355a8 100644 --- a/app/src/main/res/layout/mirror.xml +++ b/app/src/main/res/layout/mirror.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Release Mirror layout: SurfaceView for the video pipeline plus a - floating top status pill with Record and a Reconnect button (visible - only when the session is in DISCONNECTED state). The debug layout - under src/debug/res/layout/mirror.xml shadows this with a TextureView - and extra stats overlay used by the e2e screen capture. --> +<!-- Video surface with optional target navigation and reconnect controls. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#000000"> + tools:ignore="MergeRootFrame"> + <!-- Sized at runtime to the target's aspect ratio and centred, so the + black FrameLayout behind it shows as letterbox bars. --> <SurfaceView android:id="@+id/surface" android:layout_width="match_parent" @@ -39,16 +39,42 @@ android:ellipsize="end" android:text="@string/connecting"/> + + <Button + android:id="@+id/nav_back" + style="@style/Button.Secondary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/space_sm" + android:minWidth="0dp" + android:minHeight="@dimen/touch_min" + android:paddingHorizontal="@dimen/space_md" + android:paddingVertical="@dimen/space_xs" + android:text="@string/nav_back"/> + + <Button + android:id="@+id/nav_home" + style="@style/Button.Secondary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/space_sm" + android:minWidth="0dp" + android:minHeight="@dimen/touch_min" + android:paddingHorizontal="@dimen/space_md" + android:paddingVertical="@dimen/space_xs" + android:text="@string/nav_home"/> + <Button - android:id="@+id/record" + android:id="@+id/nav_recents" style="@style/Button.Secondary" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/space_sm" - android:minHeight="0dp" + android:minWidth="0dp" + android:minHeight="@dimen/touch_min" android:paddingHorizontal="@dimen/space_md" android:paddingVertical="@dimen/space_xs" - android:text="@string/record"/> + android:text="@string/nav_recents"/> <Button android:id="@+id/reconnect" @@ -56,7 +82,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/space_sm" - android:minHeight="0dp" + android:minHeight="@dimen/touch_min" android:paddingHorizontal="@dimen/space_md" android:paddingVertical="@dimen/space_xs" android:text="@string/reconnect" diff --git a/app/src/main/res/layout/settings.xml b/app/src/main/res/layout/settings.xml index 76f706b..aa2f117 100644 --- a/app/src/main/res/layout/settings.xml +++ b/app/src/main/res/layout/settings.xml @@ -51,21 +51,21 @@ style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="H.264 (default)"/> + android:text="@string/video_h264"/> <RadioButton android:id="@+id/video_h265" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="H.265"/> + android:text="@string/video_h265"/> <RadioButton android:id="@+id/video_av1" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="AV1 (requires target Android 14+)"/> + android:text="@string/video_av1"/> </RadioGroup> @@ -93,14 +93,14 @@ style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Raw PCM (1.5 Mbps, default)"/> + android:text="@string/audio_raw"/> <RadioButton android:id="@+id/audio_opus" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Opus (~128 kbps)"/> + android:text="@string/audio_opus"/> </RadioGroup> @@ -128,42 +128,42 @@ style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Original (default)"/> + android:text="@string/max_size_original"/> <RadioButton android:id="@+id/max_size_480" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="480"/> + android:text="@string/max_size_480"/> <RadioButton android:id="@+id/max_size_720" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="720"/> + android:text="@string/max_size_720"/> <RadioButton android:id="@+id/max_size_1080" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="1080"/> + android:text="@string/max_size_1080"/> <RadioButton android:id="@+id/max_size_1440" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="1440"/> + android:text="@string/max_size_1440"/> <RadioButton android:id="@+id/max_size_2160" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="2160"/> + android:text="@string/max_size_2160"/> </RadioGroup> @@ -191,35 +191,35 @@ style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="1 Mbps"/> + android:text="@string/bit_rate_1m"/> <RadioButton android:id="@+id/bit_rate_2m" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="2 Mbps"/> + android:text="@string/bit_rate_2m"/> <RadioButton android:id="@+id/bit_rate_4m" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="4 Mbps"/> + android:text="@string/bit_rate_4m"/> <RadioButton android:id="@+id/bit_rate_8m" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="8 Mbps (default)"/> + android:text="@string/bit_rate_8m"/> <RadioButton android:id="@+id/bit_rate_16m" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="16 Mbps"/> + android:text="@string/bit_rate_16m"/> </RadioGroup> @@ -247,35 +247,35 @@ style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Unlimited (default)"/> + android:text="@string/max_fps_unlimited"/> <RadioButton android:id="@+id/max_fps_30" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="30"/> + android:text="@string/max_fps_30"/> <RadioButton android:id="@+id/max_fps_60" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="60"/> + android:text="@string/max_fps_60"/> <RadioButton android:id="@+id/max_fps_90" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="90"/> + android:text="@string/max_fps_90"/> <RadioButton android:id="@+id/max_fps_120" style="@style/RadioOption" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="120"/> + android:text="@string/max_fps_120"/> </RadioGroup> @@ -294,6 +294,13 @@ android:text="@string/display"/> <CheckBox + android:id="@+id/clipboard_sync" + style="@style/RadioOption" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/clipboard_sync"/> + + <CheckBox android:id="@+id/show_status_bar" style="@style/RadioOption" android:layout_width="match_parent" @@ -302,6 +309,17 @@ </LinearLayout> + <!-- Required, not decorative: the bundled SPAKE2 library is + LGPL-3.0 and the combined work has to give the user prominent + notice of that and of where to get the source. --> + <Button + android:id="@+id/licenses" + style="@style/Button.Secondary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/space_lg" + android:text="@string/licenses"/> + </LinearLayout> </ScrollView> |