Merge branch 'azahar-emu:master' into feat/game-custom-config
This commit is contained in:
commit
880375eb7a
7 changed files with 115 additions and 16 deletions
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
|
@ -62,7 +62,7 @@ jobs:
|
|||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
macos:
|
||||
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-13') || 'macos-14' }}
|
||||
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-15-intel') || 'macos-26' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -103,7 +103,7 @@ jobs:
|
|||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
macos-universal:
|
||||
runs-on: macos-14
|
||||
runs-on: macos-26
|
||||
needs: macos
|
||||
env:
|
||||
OS: macos
|
||||
|
|
|
|||
2
externals/fmt
vendored
2
externals/fmt
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a
|
||||
Subproject commit e424e3f2e607da02742f73db84873b8084fc714c
|
||||
|
|
@ -96,6 +96,24 @@ object NativeLibrary {
|
|||
*/
|
||||
external fun onTouchMoved(xAxis: Float, yAxis: Float)
|
||||
|
||||
/**
|
||||
* Handles touch events on the secondary display.
|
||||
*
|
||||
* @param xAxis The value of the x-axis.
|
||||
* @param yAxis The value of the y-axis.
|
||||
* @param pressed To identify if the touch held down or released.
|
||||
* @return true if the pointer is within the touchscreen
|
||||
*/
|
||||
external fun onSecondaryTouchEvent(xAxis: Float, yAxis: Float, pressed: Boolean): Boolean
|
||||
|
||||
/**
|
||||
* Handles touch movement on the secondary display.
|
||||
*
|
||||
* @param xAxis The value of the instantaneous x-axis.
|
||||
* @param yAxis The value of the instantaneous y-axis.
|
||||
*/
|
||||
external fun onSecondaryTouchMoved(xAxis: Float, yAxis: Float)
|
||||
|
||||
external fun reloadSettings()
|
||||
|
||||
external fun getTitleId(filename: String): Long
|
||||
|
|
|
|||
|
|
@ -11,13 +11,16 @@ import android.hardware.display.DisplayManager
|
|||
import android.hardware.display.VirtualDisplay
|
||||
import android.os.Bundle
|
||||
import android.view.Display
|
||||
import android.view.MotionEvent
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.SurfaceView
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import android.view.WindowManager
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.display.SecondaryDisplayLayout
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
|
||||
class SecondaryDisplay(val context: Context) {
|
||||
class SecondaryDisplay(val context: Context) : DisplayManager.DisplayListener {
|
||||
private var pres: SecondaryDisplayPresentation? = null
|
||||
private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
private val vd: VirtualDisplay
|
||||
|
|
@ -31,6 +34,7 @@ class SecondaryDisplay(val context: Context) {
|
|||
null,
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION
|
||||
)
|
||||
displayManager.registerDisplayListener(this, null)
|
||||
}
|
||||
|
||||
fun updateSurface() {
|
||||
|
|
@ -41,16 +45,23 @@ class SecondaryDisplay(val context: Context) {
|
|||
NativeLibrary.secondarySurfaceDestroyed()
|
||||
}
|
||||
|
||||
private fun getExternalDisplay(context: Context): Display? {
|
||||
val dm = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
val internalId = context.display.displayId ?: Display.DEFAULT_DISPLAY
|
||||
val displays = dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)
|
||||
return displays.firstOrNull { it.displayId != internalId && it.name != "HiddenDisplay" }
|
||||
}
|
||||
|
||||
fun updateDisplay() {
|
||||
// decide if we are going to the external display or the internal one
|
||||
var display = getCustomerDisplay()
|
||||
var display = getExternalDisplay(context)
|
||||
if (display == null ||
|
||||
IntSetting.SECONDARY_DISPLAY_LAYOUT.int == SecondaryDisplayLayout.NONE.int) {
|
||||
display = vd.display
|
||||
}
|
||||
|
||||
// if our presentation is already on the right display, ignore
|
||||
if (pres?.display == display) return;
|
||||
if (pres?.display == display) return
|
||||
|
||||
// otherwise, make a new presentation
|
||||
releasePresentation()
|
||||
|
|
@ -58,29 +69,41 @@ class SecondaryDisplay(val context: Context) {
|
|||
pres?.show()
|
||||
}
|
||||
|
||||
private fun getCustomerDisplay(): Display? {
|
||||
val displays = displayManager.displays
|
||||
// code taken from MelonDS dual screen - should fix odin 2 detection bug
|
||||
return displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)
|
||||
.firstOrNull { it.displayId != Display.DEFAULT_DISPLAY && it.name != "Built-in Screen" && it.name != "HiddenDisplay"}
|
||||
}
|
||||
|
||||
fun releasePresentation() {
|
||||
pres?.dismiss()
|
||||
pres = null
|
||||
}
|
||||
|
||||
fun releaseVD() {
|
||||
displayManager.unregisterDisplayListener(this)
|
||||
vd.release()
|
||||
}
|
||||
|
||||
override fun onDisplayAdded(displayId: Int) {
|
||||
updateDisplay()
|
||||
}
|
||||
|
||||
override fun onDisplayRemoved(displayId: Int) {
|
||||
updateDisplay()
|
||||
}
|
||||
override fun onDisplayChanged(displayId: Int) {
|
||||
updateDisplay()
|
||||
}
|
||||
}
|
||||
class SecondaryDisplayPresentation(
|
||||
context: Context, display: Display, val parent: SecondaryDisplay
|
||||
) : Presentation(context, display) {
|
||||
private lateinit var surfaceView: SurfaceView
|
||||
private var touchscreenPointerId = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
)
|
||||
|
||||
// Initialize SurfaceView
|
||||
surfaceView = SurfaceView(context)
|
||||
|
|
@ -100,6 +123,42 @@ class SecondaryDisplayPresentation(
|
|||
}
|
||||
})
|
||||
|
||||
this.surfaceView.setOnTouchListener { _, event ->
|
||||
|
||||
val pointerIndex = event.actionIndex
|
||||
val pointerId = event.getPointerId(pointerIndex)
|
||||
when (event.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
if (touchscreenPointerId == -1) {
|
||||
touchscreenPointerId = pointerId
|
||||
NativeLibrary.onSecondaryTouchEvent(
|
||||
event.getX(pointerIndex),
|
||||
event.getY(pointerIndex),
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val index = event.findPointerIndex(touchscreenPointerId)
|
||||
if (index != -1) {
|
||||
NativeLibrary.onSecondaryTouchMoved(
|
||||
event.getX(index),
|
||||
event.getY(index)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
if (pointerId == touchscreenPointerId) {
|
||||
NativeLibrary.onSecondaryTouchEvent(0f, 0f, false)
|
||||
touchscreenPointerId = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
setContentView(surfaceView) // Set SurfaceView as content
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,8 +153,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
|||
if (isActionMove) {
|
||||
NativeLibrary.onTouchMoved(xPosition.toFloat(), yPosition.toFloat())
|
||||
continue
|
||||
}
|
||||
else if (isActionUp) {
|
||||
} else if (isActionUp) {
|
||||
NativeLibrary.onTouchEvent(0f, 0f, false)
|
||||
break // Up and down actions shouldn't loop
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,6 +661,25 @@ void Java_org_citra_citra_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEn
|
|||
window->OnTouchMoved((int)x, (int)y);
|
||||
}
|
||||
|
||||
jboolean Java_org_citra_citra_1emu_NativeLibrary_onSecondaryTouchEvent([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jobject obj,
|
||||
jfloat x, jfloat y,
|
||||
jboolean pressed) {
|
||||
if (!secondary_window) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return static_cast<jboolean>(secondary_window->OnTouchEvent(
|
||||
static_cast<int>(x + 0.5), static_cast<int>(y + 0.5), pressed));
|
||||
}
|
||||
|
||||
void Java_org_citra_citra_1emu_NativeLibrary_onSecondaryTouchMoved([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jobject obj,
|
||||
jfloat x, jfloat y) {
|
||||
if (secondary_window) {
|
||||
secondary_window->OnTouchMoved((int)x, (int)y);
|
||||
}
|
||||
}
|
||||
|
||||
jlong Java_org_citra_citra_1emu_NativeLibrary_getTitleId(JNIEnv* env, [[maybe_unused]] jobject obj,
|
||||
jstring j_filename) {
|
||||
std::string filepath = GetJString(env, j_filename);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!layout.bottom_screen_enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue