Android dual screen controls #820
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
stale
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-streetpea/chiaki-ng!820
Loading…
Reference in a new issue
No description provided.
Delete branch "MicheleLoiDWR/android-dual-screen-controls"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds support for dual-screen Android devices (clamshell handhelds with a second, touch-enabled display): the touch controls can move to the second display, leaving the main display to show the stream video without an overlay on top. The second display is found through Android's
DISPLAY_CATEGORY_PRESENTATIONcapability, so nothing is tied to a specific device.It's opt-in and off by default, so there's no change for existing users unless they enable it.
Based on #819 (on-screen menu button). The stream menu is how the swap button below is reached on gesture-navigation devices. Until #819 is merged this PR also shows its commit; only the second commit belongs to this PR.
I saw there was a similar PR, #708 ("Feat/dual screen support"), but it was closed and didn't include a second-screen implementation, so this is a fresh take on the same idea.
What users get
Settings → Second Screen (only shown when a presentation-capable display is present):
Swap button (in the stream menu, and on the second screen in Simplified mode): hands the second display back to the system mid-stream, e.g. to use a browser on it, and takes it back again. The controls return to the main screen as the normal overlay in the meantime.
Implementation
stream/SecondDisplayController.kt(new): discovers the second display, listens for display and input-device changes, decides Full vs Simplified, owns the presentation's lifecycle (started/stopped fromonResume/onPause), and exposesisActive/controllerState/enabled(release/reclaim).touchcontrols/SecondScreenPresentation.kt(new): anandroid.app.Presentationhosting both layouts. It'sFLAG_NOT_FOCUSABLE, so it doesn't take input focus from a physical gamepad, usesStreamThemefor the black background, and hides the system bars on the second display.StreamActivity: creates the controller when enabled, hides its own touch controls while the second screen is active, and adds the swap button to the stream menu.bindTouchControls()(TouchControlsFragment.kt): the full layout's button wiring, moved out ofDefaultTouchControlsFragmentso both screens share it. No behavior change.fragment_controls.xml: the touchpad is now centered between Share and Options instead of the screen edges, keeping its 300dp cap. It's unchanged on wide screens and shrinks rather than overlapping other controls on narrow ones, such as a near-square second display.TouchpadView.alwaysVisible: opt-in; draws the idle touchpad where there's no video behind it.SettingsFragment'sDataStorewhitelist.Testing
SecondScreenLayoutTestcovers the Auto/Full/Simplified decision; all 19 unit tests pass../gradlew lintDebug: no new warnings on the changed files.Known limitations
mainbuild on the Thor. I suspect the cause is inStreamActivity.onAttachFragment: it seems to replace the single forwarding job for each fragment it attaches, which would leave only the last-attachedTouchpadOnlyFragmentconnected to the session. It also affects controls swapped back to the main screen. I'd rather look into it in a separate PR.Notes
Developed with the assistance of Claude Code, and tested on real hardware as described above.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.