From 5112b3b4ed7423a500a894f455a36ca572fc39e0 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Thu, 28 Mar 2024 01:03:34 +0100 Subject: [PATCH] Add input tests (mouse and keyboard) --- .../androidTest/java/rs/ruffle/InputEvents.kt | 155 +++++++++++++++++ app/src/androidTest/res/raw/input_test.swf | Bin 0 -> 1239 bytes .../androidTest/res/raw/input_tests/Test.as | 35 ++++ .../androidTest/res/raw/input_tests/test.fla | Bin 0 -> 5828 bytes .../androidTest/res/raw/input_tests/test.swf | Bin 0 -> 1239 bytes app/src/main/java/rs/ruffle/PlayerActivity.kt | 3 + src/keycodes.rs | 156 +++++++++--------- src/lib.rs | 16 +- 8 files changed, 278 insertions(+), 87 deletions(-) create mode 100644 app/src/androidTest/java/rs/ruffle/InputEvents.kt create mode 100644 app/src/androidTest/res/raw/input_test.swf create mode 100644 app/src/androidTest/res/raw/input_tests/Test.as create mode 100644 app/src/androidTest/res/raw/input_tests/test.fla create mode 100644 app/src/androidTest/res/raw/input_tests/test.swf diff --git a/app/src/androidTest/java/rs/ruffle/InputEvents.kt b/app/src/androidTest/java/rs/ruffle/InputEvents.kt new file mode 100644 index 00000000..032a17d8 --- /dev/null +++ b/app/src/androidTest/java/rs/ruffle/InputEvents.kt @@ -0,0 +1,155 @@ +package rs.ruffle + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.graphics.Point +import android.graphics.Rect +import android.net.Uri +import android.view.KeyEvent +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.Until +import java.io.File +import kotlin.math.min +import kotlin.math.roundToInt +import org.hamcrest.CoreMatchers +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +private const val BASIC_SAMPLE_PACKAGE = "rs.ruffle" +private const val LAUNCH_TIMEOUT = 5000L +private const val SWF_WIDTH = 550.0 +private const val SWF_HEIGHT = 400.0 + +@RunWith(AndroidJUnit4::class) +class InputEvents { + private lateinit var device: UiDevice + private lateinit var traceOutput: File + private lateinit var swfFile: File + + @Before + fun startMainActivityFromHomeScreen() { + // Initialize UiDevice instance + device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + // Start from the home screen + device.pressHome() + + // Wait for launcher + val launcherPackage: String = device.launcherPackageName + ViewMatchers.assertThat(launcherPackage, CoreMatchers.notNullValue()) + device.wait( + Until.hasObject(By.pkg(launcherPackage).depth(0)), + LAUNCH_TIMEOUT + ) + + // Launch the app + val context = ApplicationProvider.getApplicationContext() + traceOutput = File.createTempFile("trace", ".txt", context.cacheDir) + swfFile = File.createTempFile("movie", ".swf", context.cacheDir) + val resources = InstrumentationRegistry.getInstrumentation().context.resources + val inStream = resources.openRawResource( + rs.ruffle.test.R.raw.input_test + ) + val bytes = inStream.readBytes() + swfFile.writeBytes(bytes) + val intent = context.packageManager.getLaunchIntentForPackage( + BASIC_SAMPLE_PACKAGE + )?.apply { + component = ComponentName("rs.ruffle", "rs.ruffle.PlayerActivity") + data = Uri.fromFile(swfFile) + putExtra("traceOutput", traceOutput.absolutePath) + // Clear out any previous instances + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) + } + context.startActivity(intent) + + // Wait for the app to appear + device.wait( + Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), + LAUNCH_TIMEOUT + ) + } + + @Test + fun clickEvents() { + device.waitForWindowUpdate(null, 1000) + ViewMatchers.assertThat(device, CoreMatchers.notNullValue()) + + val player = device.findObject(By.desc("Ruffle Player")) + + val red = screenToSwf(player.visibleBounds, Point(50, 50)) + val blue = screenToSwf(player.visibleBounds, Point(500, 350)) + device.click(red) + device.click(blue) + device.drag(red.x, red.y, blue.x, blue.y, 100) + device.waitForWindowUpdate(null, 500) + + val trace = traceOutput.readLines() + ViewMatchers.assertThat( + trace, + CoreMatchers.equalTo( + listOf( + "Test started!", + "red received mouseDown", + "red received mouseUp", + "red received click", + "blue received mouseDown", + "blue received mouseUp", + "blue received click", + "red received mouseDown", + "blue received mouseUp" + ) + ) + ) + } + + @Test + fun keyEvents() { + device.waitForWindowUpdate(null, 1000) + ViewMatchers.assertThat(device, CoreMatchers.notNullValue()) + + device.pressKeyCode(KeyEvent.KEYCODE_A) + device.pressKeyCode(KeyEvent.KEYCODE_B) + + device.waitForWindowUpdate(null, 500) + + val trace = traceOutput.readLines() + ViewMatchers.assertThat( + trace, + CoreMatchers.equalTo( + listOf( + "Test started!", + "keyDown: keyCode = 65, charCode = 97", + "keyUp: keyCode = 65, charCode = 97", + "keyDown: keyCode = 66, charCode = 98", + "keyUp: keyCode = 66, charCode = 98" + ) + ) + ) + } + + private fun screenToSwf(playerBounds: Rect, point: Point): Point { + val stretchX = playerBounds.width() / SWF_WIDTH + val stretchY = playerBounds.height() / SWF_HEIGHT + val scaleFactor = min(stretchX, stretchY) + val swfScreenWidth = SWF_WIDTH * scaleFactor + val swfScreenHeight = SWF_HEIGHT * scaleFactor + val swfOffsetX = (playerBounds.width() - swfScreenWidth) / 2 + val swfOffsetY = (playerBounds.height() - swfScreenHeight) / 2 + return Point( + (playerBounds.left + swfOffsetX + point.x * scaleFactor).roundToInt(), + (playerBounds.top + swfOffsetY + point.y * scaleFactor).roundToInt() + ) + } +} + +private fun UiDevice.click(point: Point) { + this.click(point.x, point.y) +} diff --git a/app/src/androidTest/res/raw/input_test.swf b/app/src/androidTest/res/raw/input_test.swf new file mode 100644 index 0000000000000000000000000000000000000000..4526f3aa9cac81e2614117c1ec21116b8053c497 GIT binary patch literal 1239 zcmV;|1StDMS5psa2><|ioTXLEZrer_of$qx4=a-6XWopHwm>V1lq^3)*lHX}4va)q z5Iab^2qKys*=#70ASv5g6fIhy+iv;+{u6&dyHL967xWLh>c+jKC_fS>O;bYR+&gpc zId={(hX+V_iBS3wp;?S-BGj0tyQbrtc2^2~ZQJhot8;S^>_Nvl zf$e&E&9JvwUbj2)f#%4CydnoU5TsUJrunwJW!qL|Er^oVEzR4N9=mp%c^<%PmQ>wb zlycH`&$JAwv|Lz`-^@IN#cJ@c6qRBrr_ASyOIwAqTAWu)r7x6%swii2hmph72JBysK&ws+&?~nGj z`VNzyFwgF}I)m^#(bH)()Qzs^Yh9gf)G9EMH%&ubTCOiw*A{B!V!c|g7Yb_&rL}VP zeqC8F-!Cjy*TapTPaUDvY`xcET|YuI{sY>X)Dc?KHFr$tj|))ii}SV8^5XpB()&>_ zfHe?COV@eIroSp7*9F%0M)_(x(2?w?{wM>T(7&+L*xMmn3?jzIl zK_=Hr!wjUJ_=4|hI!gul67;m|Gvl@Z#t!4VT8AYhm+36%6^ZxZJxVm1PdDo?Yt3h0 zWdJE8A7RCYYfm2w)khoEhrAAz#H?s>OqE`-e$_UZv?|faOl2i~S97D;*vO7OtbZL+ zh=K9+u{hjvI%Eq}(0qNDx#JsMpF#CLlsAl+J||Jth7X_#+~TI=nm!Y!@iaFr%*JLo zbdzF22~RnZVoFJja&bx$lq9JzMuik5mng|lVVsf)N+v0pqGXzq87j9gx_;?V|eWf!29Jy91Y*Npu592^B;J|leD_k BUb+AP literal 0 HcmV?d00001 diff --git a/app/src/androidTest/res/raw/input_tests/Test.as b/app/src/androidTest/res/raw/input_tests/Test.as new file mode 100644 index 00000000..0f37d2d6 --- /dev/null +++ b/app/src/androidTest/res/raw/input_tests/Test.as @@ -0,0 +1,35 @@ +package { + import flash.display.MovieClip; + import flash.events.MouseEvent; + import flash.display.DisplayObject; + import flash.events.KeyboardEvent; + + public class Test extends MovieClip { + public function Test() { + trace("Test started!"); + + addKeyListeners("stage", stage); + addMouseListeners("red", red); + addMouseListeners("blue", blue); + } + + function addMouseListeners(name: String, clip: DisplayObject) { + var listener = function(event: MouseEvent) { + trace(name + " received " + event.type); + }; + clip.addEventListener(MouseEvent.MOUSE_DOWN, listener); + clip.addEventListener(MouseEvent.MOUSE_UP, listener); + //clip.addEventListener(MouseEvent.MOUSE_OVER, listener); + //clip.addEventListener(MouseEvent.MOUSE_OUT, listener); + clip.addEventListener(MouseEvent.CLICK, listener); + } + + function addKeyListeners(name: String, clip: DisplayObject) { + var listener = function(event: KeyboardEvent) { + trace(event.type + ": keyCode = " + event.keyCode + ", charCode = " + event.charCode); + }; + stage.addEventListener(KeyboardEvent.KEY_DOWN, listener); + stage.addEventListener(KeyboardEvent.KEY_UP, listener); + } + } +} diff --git a/app/src/androidTest/res/raw/input_tests/test.fla b/app/src/androidTest/res/raw/input_tests/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..b1635fc0f7c8c1ffce6b93c737b32c4a7dee856d GIT binary patch literal 5828 zcmbtYby$;Y*dGi;S{ek#K#*{Rh#;Xzr!YE|+@X6&Ba99yVWb131tbLq2uLa^5~CzU zx+En;zTr6>&+$6n_s{q2diK`+d+zsopF4k06(Alp0B{)q&`kHyXC}1-5&{5#^NGC$ zfWzG2e4c;ULp9a)4R~d=ZbSbij+OX(oQta}Noz`J8u0(`Qs)alkkgjpRZ^4xOAPn& z<)6AWEEkrcKmgzs82~_z6_ZteAnRn|?f`SdzJi1OhMtkrgaEaFX7!n=*8s=2U~Q#5 zTbiqy4Q#N9dWC0qI?}1GO;V4QWp3aRg;eJj*Ca25wBK72uiauw|FU|p7`YHdgrO|q zF^t+x0&{05iAvU%EVzp5djmVScri81YnzK=JyvznR=Kp4Bch>CM|E>(f!gKVpf4qr zx*Q|kGQj%jmmQ(nsoNuU{CAvs~aSDXK__ArgZr<_%Y(;Z{bqbIN!5fbEPHe zXX-z5srN1}$=&Xd2$9e4ypg(4*EuiUA*KAn!+8GP@ngQE{FFkBUFRYHA#Qzw)BRw9_TEmHXjr;7feG#B6h8ojS1M z=TcENm)lLsX7m&Hh?Kwej>c+HE8`G)wGlCEWw*vManeti2?US2T@vL}tEKZ{^pOgC z1KtB|aEv|+ry8eRQX-@F6G_B`L7G->`q_V`;x2__jeiWBiZTA&X=B;k+ zBFV#?!FMbUsTtDm>BQ9H%_7~3WNzMIK71OlsfX?f@v|af4KRm1%KH#H%lW7{mwVvz zJLY?KFaia1zR?LR>ZIn@vs0JJ`G5p&1>d{69H;gPIkx1J5~+GgZV^Yp@rK@d9^54B zoOUyPhUENL^?2At4fb{H;7-weaXdb+*q$4wn-tfQkFI4XvMap)aE)jMCG6$-5G+qq zZPq9jDe1;pL8iamnfP(nuB~YCG)`MVf8kWd@JOTQ#+GEo53vf$wJ+m;*r&K0uiMw4 znENlaGZ87M(XPE4G^Z908=8On*g1}aN=>NX7KEc{t7D$^j)^KaMU}d2p~|2)i|@zv zl^-~z#`69}(+r)*kB3XF*EVn%FU3rhtKkodpssvq#EbJ2j%K&q0Hd;(@S78@=7^Jf^f_=P7OV^ zDG(}{d8EQ;Pwfi}XF6RM0cJ-nZj4y${`aBxw38YH;U3;}9zpAmUCfzPC2q-zJc082 z1ON2V3+H=dNN3=P3jnxbosZ_9KI#C2n^~H{&3?LI@{D7;0CnfqE;a3&sg{&0h9z-4 z9I_kuMkDeQj?B(iwOdHUNmq(D%wwzdQdplL0i~nvbPX-aFP!fzeS5!DB?Wp!%RmS! z0=OMt$&1<9Jt4=J&Cc;DE9>Thh1gdzY4;T08ACg3iQgQ?_F{L~D)KS2}zU>rK8&bTdoP-*Fg z$JR>i(DDy?CLKpB_ND6e#+-GdG9jYwv~DR?gzYKbh&OrISN3C9gFTV_+sY=3WywN* z4zVEE87V?E8UX}lxSq0SUlWP z;QSZ?XM3*r^Kh1==;V3F{Z%X`CuL=5U6*3QYWAk-`ySq4McZY45f0in@qzH0|wH&%MZGMwst(OokOt%ee<1C zyc{=5yNugPUkj7J$LbmW#5KB0T(s~3JNDk?mR2aWcmyMr( z!)#w_RzaSQXwc-A>q`pkMS-@&cRAhMbOQWke(59mwXA#nFTF=>d+_VW4h(}pCuudj zNr7aQ` zckayeKE){ePQv`@juriCH`WMawtW&HyQj2!+MpdDF1)*R;fQCxN`UG$T+sz~ldlRj z_h&+E3j)D_39rB@^_8g7LqjkAI8A>d$QyIQWBx1ndLj2BUIQPZ)%?^oU8zQC##Yeq zeP%baSY>D2E12EQv~pRcmm8;6ebWHUN`^w;sF}6Fe?q zA2fU9V{Kcb7AOW(rrM&;4X?f52n^g6zT#jlNwD`-)?Mow&;34ps@MJd#$kQCnl7cZ zJjc9N3;hkVMZxT4khC=B9jm@cAe>4`PMQ6aNP7){jFPNW!k6xvb*s;}^-19BtM=CX z-6pTsj+r7wm{$^w4LIT<<)AXH8A6L#BjIN~g`YwL<7E#cD?2ph3rJf?9rQYAkLzSw zm(v7O?LG+w&IatNG8jCexT?bTC7fFHIk!#nZQPr0<=D*NbBI%1s%NqTXk4vg7mv5F zU=><|&y!%HC)|pyU$o#8MMjj2-h21vwt+*0c+myJ6Rjl_Lku${N2+U^&VR5Ytq8rY zeyoP3)s;NA?K7VU>zHNd2 zbff?9?(>5YG_--f`T57a%}Gz9KryQ*=_^SL`FhXhOl@Dx;LVS!UT@<)`a_zwRyMcI zH#?S-#f2&(v%S$DZ=B#(h^!ZB2uK3{_YI)@Z8 zvh4UG8<+Cf-GA7uA>=6AW%Q8T+ya8naijN`evfP`()g>+b!(KuRtYpBYpme4vf#pf zzO~DBZHEB{lGH-SWmR#nZa9L7mAX+41FaeJZ40$o5h`c|cI{vNB4={H1p0glQDDq0p* zcsMa)sd?rpKq)k5Dc=#-&5A*qlmEf8VUR1o$fMVs%?I$T#`>Uz_ZqAT*4(gz z>_?eaP~E)l#V*+-k*=F2BUPV4*H3hk-#1Q+Ikq^h|R=2>mrSMkkxC z;M>ONQ@yPx0@KnMGCNz_wS?PfUpVvgCOg#Y85xvbw5b2^&AiBf)w&6jN8}OF$@SqY z6-i&GH`mCQgoLo{sy}>otvS(F8FEws$dZ(3Q53k%h z+t#EO82ivSzbHg9$|T$Wm|!d{CMImePux>!^Z!;A$;O|Bn@rKFn7)SMrr`H%4f$~< zA21e4&gVcl6_8{|V{x#Ft@K60v)8LajivX2N90@aASeE%8%_Dih+g^(3(@J1e($D^ z@s)O?3!i-9I<0Fub22lk{KRgQP&h8On@i!I1nJt-_ibp6uq2 zMeVC5Gx|EXiHh_#n!4uL!`+T1G!CvhdO%*LJv?|qOUFM!IdDR6VyR3R>*qy%e|l?> zWOQ8YZoO4yO<;tr*qGRUW+Afr zmB!ZK!y=Xf_lS8M`OBN#nOTZHttaS&9SW+)ggDLl-6$mdbgllTw?!oJiTV~VIQ9qW zMTzrg^Np=){vMRrvjtWYF;<(IrIR`ACsXi~AUJO;q5!`7mtxJ|q~HJm zW7xj_3Ko7r5S*($FWKC+dSVa))SuJ^&!FOK6{YibBz1$VHwSxh>8j+oCRA~Nx9@-M z8gLklAvcxUT$^(9_F028i}*iZ7es4HNa?T*nd{QDb`a#n+>-9DTu){>h0Hv|$&3DO zKkDx}tMrxcqcpzFJC~r!@akm(jhgvW0To3Wm8a>H(I3HceADl#z<6<`NIp>PiU55_ zkjG0&S~>dnSzC9>hrVcBc?1MncvXuJcpF}UtJL{;A@3cs;wPMTam zrI<@mW~_Sic;R*idAKBJ5Vt=7fTu{Ab# z>Qpt-I(x~iKzhY|&MO7J&xy=>$h4xn^ws)ING$z3f<3aVFO@ciq^0BTC8MB1$vccP zXWpY?Cb*+R*By9lxmAo_QW}cxpblKG= zQkz?YeDA}Jkh}_8Fs_19uD>rPwBGA2PNTTExP{MlveVjf$`j4%lv-K_L)EcU5;=AmHcv7OLQTbM4v**RAOFUQz(#5qZm4VE>qu8CnA_()mMOG5- zMv~P^ox)yFX%rZCWSO zPK5RQ1bJ@{hhZ*<~?&I|DG1jsM&5!UMe z*7;95NDseW;J?H5 zuLYpkuYa*!7s2~?^zUKf7n&BE&Mwe@1&s^v1@ruSqWJ|L$L6++v;$Sa$9_rxfEfGh N#U?U(tbqam{{ys@zbOC! literal 0 HcmV?d00001 diff --git a/app/src/androidTest/res/raw/input_tests/test.swf b/app/src/androidTest/res/raw/input_tests/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..4526f3aa9cac81e2614117c1ec21116b8053c497 GIT binary patch literal 1239 zcmV;|1StDMS5psa2><|ioTXLEZrer_of$qx4=a-6XWopHwm>V1lq^3)*lHX}4va)q z5Iab^2qKys*=#70ASv5g6fIhy+iv;+{u6&dyHL967xWLh>c+jKC_fS>O;bYR+&gpc zId={(hX+V_iBS3wp;?S-BGj0tyQbrtc2^2~ZQJhot8;S^>_Nvl zf$e&E&9JvwUbj2)f#%4CydnoU5TsUJrunwJW!qL|Er^oVEzR4N9=mp%c^<%PmQ>wb zlycH`&$JAwv|Lz`-^@IN#cJ@c6qRBrr_ASyOIwAqTAWu)r7x6%swii2hmph72JBysK&ws+&?~nGj z`VNzyFwgF}I)m^#(bH)()Qzs^Yh9gf)G9EMH%&ubTCOiw*A{B!V!c|g7Yb_&rL}VP zeqC8F-!Cjy*TapTPaUDvY`xcET|YuI{sY>X)Dc?KHFr$tj|))ii}SV8^5XpB()&>_ zfHe?COV@eIroSp7*9F%0M)_(x(2?w?{wM>T(7&+L*xMmn3?jzIl zK_=Hr!wjUJ_=4|hI!gul67;m|Gvl@Z#t!4VT8AYhm+36%6^ZxZJxVm1PdDo?Yt3h0 zWdJE8A7RCYYfm2w)khoEhrAAz#H?s>OqE`-e$_UZv?|faOl2i~S97D;*vO7OtbZL+ zh=K9+u{hjvI%Eq}(0qNDx#JsMpF#CLlsAl+J||Jth7X_#+~TI=nm!Y!@iaFr%*JLo zbdzF22~RnZVoFJja&bx$lq9JzMuik5mng|lVVsf)N+v0pqGXzq87j9gx_;?V|eWf!29Jy91Y*Npu592^B;J|leD_k BUb+AP literal 0 HcmV?d00001 diff --git a/app/src/main/java/rs/ruffle/PlayerActivity.kt b/app/src/main/java/rs/ruffle/PlayerActivity.kt index 01a71a62..924621ae 100644 --- a/app/src/main/java/rs/ruffle/PlayerActivity.kt +++ b/app/src/main/java/rs/ruffle/PlayerActivity.kt @@ -141,6 +141,9 @@ class PlayerActivity : GameActivity() { layout.id = contentViewId setContentView(layout) mSurfaceView = InputEnabledSurfaceView(this) + + mSurfaceView.contentDescription = "Ruffle Player" + val placeholder = findViewById(R.id.placeholder) val pars = placeholder.layoutParams as ConstraintLayout.LayoutParams val parent = placeholder.parent as ViewGroup diff --git a/src/keycodes.rs b/src/keycodes.rs index 8c4e51a4..f03565b4 100644 --- a/src/keycodes.rs +++ b/src/keycodes.rs @@ -1,85 +1,85 @@ use android_activity::input::Keycode as Android; use ruffle_core::events::KeyCode as Ruffle; -pub fn android_keycode_to_ruffle(android: Android) -> Option { +pub fn android_keycode_to_ruffle(android: Android) -> Option<(Ruffle, Option)> { Some(match android { - Android::A => Ruffle::A, - Android::B => Ruffle::B, - Android::C => Ruffle::C, - Android::D => Ruffle::D, - Android::E => Ruffle::E, - Android::F => Ruffle::F, - Android::G => Ruffle::G, - Android::H => Ruffle::H, - Android::I => Ruffle::I, - Android::J => Ruffle::J, - Android::K => Ruffle::K, - Android::L => Ruffle::L, - Android::M => Ruffle::M, - Android::N => Ruffle::N, - Android::O => Ruffle::O, - Android::P => Ruffle::P, - Android::Q => Ruffle::Q, - Android::R => Ruffle::R, - Android::S => Ruffle::S, - Android::T => Ruffle::T, - Android::U => Ruffle::U, - Android::V => Ruffle::V, - Android::W => Ruffle::W, - Android::X => Ruffle::X, - Android::Y => Ruffle::Y, - Android::Z => Ruffle::Z, - Android::Comma => Ruffle::Comma, - Android::Period => Ruffle::Period, - Android::Tab => Ruffle::Tab, - Android::Space => Ruffle::Space, - Android::Enter => Ruffle::Return, - Android::Del => Ruffle::Delete, - Android::Grave => Ruffle::Grave, - Android::Minus => Ruffle::Minus, - Android::Equals => Ruffle::Equals, - Android::LeftBracket => Ruffle::LBracket, - Android::RightBracket => Ruffle::RBracket, - Android::Backslash => Ruffle::Backslash, - Android::Semicolon => Ruffle::Semicolon, - Android::Apostrophe => Ruffle::Apostrophe, - Android::Slash => Ruffle::Slash, - Android::Plus => Ruffle::Plus, - Android::PageUp => Ruffle::PgUp, - Android::PageDown => Ruffle::PgDown, - Android::Escape => Ruffle::Escape, - Android::ForwardDel => Ruffle::Delete, - Android::CapsLock => Ruffle::CapsLock, - Android::ScrollLock => Ruffle::ScrollLock, - Android::MoveHome => Ruffle::Home, - Android::MoveEnd => Ruffle::End, - Android::Insert => Ruffle::Insert, - Android::F1 => Ruffle::F1, - Android::F2 => Ruffle::F2, - Android::F3 => Ruffle::F3, - Android::F4 => Ruffle::F4, - Android::F5 => Ruffle::F5, - Android::F6 => Ruffle::F6, - Android::F7 => Ruffle::F7, - Android::F8 => Ruffle::F8, - Android::F9 => Ruffle::F9, - Android::F10 => Ruffle::F10, - Android::F11 => Ruffle::F11, - Android::F12 => Ruffle::F12, - Android::Numpad0 => Ruffle::Numpad0, - Android::Numpad1 => Ruffle::Numpad1, - Android::Numpad2 => Ruffle::Numpad2, - Android::Numpad3 => Ruffle::Numpad3, - Android::Numpad4 => Ruffle::Numpad4, - Android::Numpad5 => Ruffle::Numpad5, - Android::Numpad6 => Ruffle::Numpad6, - Android::Numpad7 => Ruffle::Numpad7, - Android::Numpad8 => Ruffle::Numpad8, - Android::Numpad9 => Ruffle::Numpad9, - Android::NumpadDivide => Ruffle::NumpadSlash, - Android::NumpadSubtract => Ruffle::NumpadMinus, - Android::NumpadDot => Ruffle::NumpadPeriod, - Android::NumpadEnter => Ruffle::NumpadEnter, + Android::A => (Ruffle::A, Some('a')), + Android::B => (Ruffle::B, Some('b')), + Android::C => (Ruffle::C, Some('c')), + Android::D => (Ruffle::D, Some('d')), + Android::E => (Ruffle::E, Some('e')), + Android::F => (Ruffle::F, Some('f')), + Android::G => (Ruffle::G, Some('g')), + Android::H => (Ruffle::H, Some('h')), + Android::I => (Ruffle::I, Some('i')), + Android::J => (Ruffle::J, Some('j')), + Android::K => (Ruffle::K, Some('k')), + Android::L => (Ruffle::L, Some('l')), + Android::M => (Ruffle::M, Some('m')), + Android::N => (Ruffle::N, Some('n')), + Android::O => (Ruffle::O, Some('o')), + Android::P => (Ruffle::P, Some('p')), + Android::Q => (Ruffle::Q, Some('q')), + Android::R => (Ruffle::R, Some('r')), + Android::S => (Ruffle::S, Some('s')), + Android::T => (Ruffle::T, Some('t')), + Android::U => (Ruffle::U, Some('u')), + Android::V => (Ruffle::V, Some('v')), + Android::W => (Ruffle::W, Some('w')), + Android::X => (Ruffle::X, Some('x')), + Android::Y => (Ruffle::Y, Some('y')), + Android::Z => (Ruffle::Z, Some('z')), + Android::Comma => (Ruffle::Comma, Some(',')), + Android::Period => (Ruffle::Period, Some('.')), + Android::Tab => (Ruffle::Tab, Some('\t')), + Android::Space => (Ruffle::Space, Some(' ')), + Android::Enter => (Ruffle::Return, Some(13 as char)), + Android::Del => (Ruffle::Backspace, Some(8 as char)), + Android::Grave => (Ruffle::Grave, Some('`')), + Android::Minus => (Ruffle::Minus, Some('-')), + Android::Equals => (Ruffle::Equals, Some('=')), + Android::LeftBracket => (Ruffle::LBracket, Some('(')), + Android::RightBracket => (Ruffle::RBracket, Some(')')), + Android::Backslash => (Ruffle::Backslash, Some('\\')), + Android::Semicolon => (Ruffle::Semicolon, Some(';')), + Android::Apostrophe => (Ruffle::Apostrophe, Some('\'')), + Android::Slash => (Ruffle::Slash, Some('/')), + Android::Plus => (Ruffle::Plus, Some('+')), + Android::PageUp => (Ruffle::PgUp, None), + Android::PageDown => (Ruffle::PgDown, None), + Android::Escape => (Ruffle::Escape, None), + Android::ForwardDel => (Ruffle::Delete, Some(127 as char)), + Android::CapsLock => (Ruffle::CapsLock, None), + Android::ScrollLock => (Ruffle::ScrollLock, None), + Android::MoveHome => (Ruffle::Home, None), + Android::MoveEnd => (Ruffle::End, None), + Android::Insert => (Ruffle::Insert, None), + Android::F1 => (Ruffle::F1, None), + Android::F2 => (Ruffle::F2, None), + Android::F3 => (Ruffle::F3, None), + Android::F4 => (Ruffle::F4, None), + Android::F5 => (Ruffle::F5, None), + Android::F6 => (Ruffle::F6, None), + Android::F7 => (Ruffle::F7, None), + Android::F8 => (Ruffle::F8, None), + Android::F9 => (Ruffle::F9, None), + Android::F10 => (Ruffle::F10, None), + Android::F11 => (Ruffle::F11, None), + Android::F12 => (Ruffle::F12, None), + Android::Numpad0 => (Ruffle::Numpad0, Some('0')), + Android::Numpad1 => (Ruffle::Numpad1, Some('1')), + Android::Numpad2 => (Ruffle::Numpad2, Some('2')), + Android::Numpad3 => (Ruffle::Numpad3, Some('3')), + Android::Numpad4 => (Ruffle::Numpad4, Some('4')), + Android::Numpad5 => (Ruffle::Numpad5, Some('5')), + Android::Numpad6 => (Ruffle::Numpad6, Some('6')), + Android::Numpad7 => (Ruffle::Numpad7, Some('7')), + Android::Numpad8 => (Ruffle::Numpad8, Some('8')), + Android::Numpad9 => (Ruffle::Numpad9, Some('9')), + Android::NumpadDivide => (Ruffle::NumpadSlash, Some('/')), + Android::NumpadSubtract => (Ruffle::NumpadMinus, Some('-')), + Android::NumpadDot => (Ruffle::NumpadPeriod, Some('.')), + Android::NumpadEnter => (Ruffle::NumpadEnter, Some(13 as char)), _ => return None, }) } diff --git a/src/lib.rs b/src/lib.rs index 72c79bb4..a57e7ea7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,20 +325,18 @@ fn run(app: AndroidApp) { } InputEvent::KeyEvent(event) => { if let Some(player) = playerbox.as_ref() { - let Some(key_code) = + let Some((key_code, key_char)) = android_keycode_to_ruffle(event.key_code()) else { return InputStatus::Unhandled; }; let ruffle_event = match event.action() { - KeyAction::Down => PlayerEvent::KeyDown { - key_code, - key_char: None, - }, - KeyAction::Up => PlayerEvent::KeyUp { - key_code, - key_char: None, - }, + KeyAction::Down => { + PlayerEvent::KeyDown { key_code, key_char } + } + KeyAction::Up => { + PlayerEvent::KeyUp { key_code, key_char } + } _ => return InputStatus::Unhandled, }; player