mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-14 18:57:07 -07:00
Add Stream Display Options: Normal, Zoom and Stretch (#146)
This commit is contained in:
parent
d7372394a2
commit
4b17137855
6 changed files with 147 additions and 23 deletions
|
@ -25,6 +25,7 @@ import android.os.Bundle
|
|||
import android.os.Handler
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.TextureView
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
@ -38,6 +39,7 @@ import com.metallic.chiaki.common.LogManager
|
|||
import com.metallic.chiaki.common.Preferences
|
||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||
import com.metallic.chiaki.lib.ConnectInfo
|
||||
import com.metallic.chiaki.lib.ConnectVideoProfile
|
||||
import com.metallic.chiaki.session.*
|
||||
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
|
||||
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
|
||||
|
@ -99,6 +101,17 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
showOverlay()
|
||||
}
|
||||
|
||||
displayModeToggle.addOnButtonCheckedListener {group, checkedId, _ ->
|
||||
// following 'if' is a workaround until selectionRequired for MaterialButtonToggleGroup
|
||||
// comes out of alpha.
|
||||
// See https://stackoverflow.com/questions/56164004/required-single-selection-on-materialbuttontogglegroup
|
||||
if (displayModeToggle.checkedButtonId == -1)
|
||||
displayModeToggle.check(checkedId)
|
||||
|
||||
adjustTextureViewAspect()
|
||||
showOverlay()
|
||||
}
|
||||
|
||||
viewModel.session.attachToTextureView(textureView)
|
||||
viewModel.session.state.observe(this, Observer { this.stateChanged(it) })
|
||||
textureView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
||||
|
@ -294,33 +307,73 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
|
||||
private fun adjustTextureViewAspect()
|
||||
{
|
||||
val contentWidth = viewModel.session.connectInfo.videoProfile.width.toFloat()
|
||||
val contentHeight = viewModel.session.connectInfo.videoProfile.height.toFloat()
|
||||
val viewWidth = textureView.width.toFloat()
|
||||
val viewHeight = textureView.height.toFloat()
|
||||
val contentAspect = contentHeight / contentWidth
|
||||
|
||||
val width: Float
|
||||
val height: Float
|
||||
if(viewHeight > viewWidth * contentAspect)
|
||||
{
|
||||
width = viewWidth
|
||||
height = viewWidth * contentAspect
|
||||
}
|
||||
else
|
||||
{
|
||||
width = viewHeight / contentAspect
|
||||
height = viewHeight
|
||||
}
|
||||
val displayInfo = DisplayInfo(viewModel.session.connectInfo.videoProfile, textureView)
|
||||
val resolution = displayInfo.computeResolutionFor(displayModeToggle.checkedButtonId)
|
||||
|
||||
Matrix().also {
|
||||
textureView.getTransform(it)
|
||||
it.setScale(width / viewWidth, height / viewHeight)
|
||||
it.postTranslate((viewWidth - width) * 0.5f, (viewHeight - height) * 0.5f)
|
||||
it.setScale(resolution.width / displayInfo.viewWidth, resolution.height / displayInfo.viewHeight)
|
||||
it.postTranslate((displayInfo.viewWidth - resolution.width) * 0.5f, (displayInfo.viewHeight - resolution.height) * 0.5f)
|
||||
textureView.setTransform(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
|
||||
override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DisplayInfo constructor(val videoProfile: ConnectVideoProfile, val textureView: TextureView)
|
||||
{
|
||||
val contentWidth : Float get() = videoProfile.width.toFloat()
|
||||
val contentHeight : Float get() = videoProfile.height.toFloat()
|
||||
val viewWidth : Float get() = textureView.width.toFloat()
|
||||
val viewHeight : Float get() = textureView.height.toFloat()
|
||||
val contentAspect : Float get() = contentHeight / contentWidth
|
||||
|
||||
fun computeResolutionFor(displayModeButtonId: Int) : Resolution
|
||||
{
|
||||
when (displayModeButtonId)
|
||||
{
|
||||
R.id.display_mode_stretch_button -> return computeStrechedResolution()
|
||||
R.id.display_mode_zoom_button -> return computeZoomedResolution()
|
||||
else -> return computeNormalResolution()
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeStrechedResolution(): Resolution
|
||||
{
|
||||
return Resolution(viewWidth, viewHeight)
|
||||
}
|
||||
|
||||
private fun computeZoomedResolution(): Resolution
|
||||
{
|
||||
if (viewHeight > viewWidth * contentAspect)
|
||||
{
|
||||
val zoomFactor = viewHeight / contentHeight
|
||||
return Resolution(contentWidth * zoomFactor, viewHeight)
|
||||
}
|
||||
else
|
||||
{
|
||||
val zoomFactor = viewWidth / contentWidth
|
||||
return Resolution(viewWidth, contentHeight * zoomFactor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeNormalResolution(): Resolution
|
||||
{
|
||||
if (viewHeight > viewWidth * contentAspect)
|
||||
{
|
||||
return Resolution(viewWidth, viewWidth * contentAspect)
|
||||
}
|
||||
else
|
||||
{
|
||||
return Resolution(viewHeight / contentAspect, viewHeight)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
data class Resolution(val width: Float, val height: Float)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?attr/colorAccent" android:state_checked="true"/>
|
||||
<item android:color="@android:color/white"/>
|
||||
</selector>
|
9
android/app/src/main/res/drawable/ic_display_normal.xml
Normal file
9
android/app/src/main/res/drawable/ic_display_normal.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:width="24dp"
|
||||
android:height="24dp">
|
||||
<path
|
||||
android:pathData="M19 5H5c-1.1 0 -2 0.9 -2 2v10c0 1.1 0.9 2 2 2h14c1.1 0 2 -0.9 2 -2V7c0 -1.1 -0.9 -2 -2 -2zm0 12H5V7h14v10z"
|
||||
android:fillColor="#000000" />
|
||||
</vector>
|
9
android/app/src/main/res/drawable/ic_display_stretch.xml
Normal file
9
android/app/src/main/res/drawable/ic_display_stretch.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:width="24dp"
|
||||
android:height="24dp">
|
||||
<path
|
||||
android:pathData="M7 14H5v5h5v-2H7v-3zm-2 -4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"
|
||||
android:fillColor="#000000" />
|
||||
</vector>
|
13
android/app/src/main/res/drawable/ic_display_zoom.xml
Normal file
13
android/app/src/main/res/drawable/ic_display_zoom.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:width="24dp"
|
||||
android:height="24dp">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0 0h24v24H0z" />
|
||||
<path
|
||||
android:pathData="M15 3l2.3 2.3 -2.89 2.87 1.42 1.42L18.7 6.7 21 9V3zM3 9l2.3 -2.3 2.87 2.89 1.42 -1.42L6.7 5.3 9 3H3zm6 12l-2.3 -2.3 2.89 -2.87 -1.42 -1.42L5.3 17.3 3 15v6zm12 -6l-2.3 2.3 -2.87 -2.89 -1.42 1.42 2.89 2.87L15 21h6z"
|
||||
android:fillColor="#000000" />
|
||||
</group>
|
||||
</vector>
|
|
@ -34,8 +34,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="bottom"
|
||||
tools:paddingRight="12dp"
|
||||
tools:paddingTop="25dp"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -69,8 +67,45 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:switchPadding="8dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/displayModeToggle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:singleSelection="true"
|
||||
app:checkedButton="@id/display_mode_normal_button">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:id="@+id/display_mode_normal_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_display_normal"
|
||||
app:iconTint="@color/stream_material_button_icon_tint"
|
||||
app:strokeColor="@color/stream_text"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:id="@+id/display_mode_zoom_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_display_zoom"
|
||||
app:iconTint="@color/stream_material_button_icon_tint"
|
||||
app:strokeColor="@color/stream_text"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:id="@+id/display_mode_stretch_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_display_stretch"
|
||||
app:iconTint="@color/stream_material_button_icon_tint"
|
||||
app:strokeColor="@color/stream_text"/>
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</FrameLayout>
|
Loading…
Add table
Add a link
Reference in a new issue