MainActivity.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //% IMPORTS
  2. import android.view.ViewGroup;
  3. import android.view.WindowInsets.Type;
  4. import android.view.inputmethod.EditorInfo;
  5. import android.text.InputType;
  6. import java.util.HashMap;
  7. import videodecode.VideoDecoder;
  8. import textinput.InputConnection;
  9. import textinput.Settings;
  10. import textinput.Listener;
  11. import textinput.State;
  12. import textinput.GameTextInput;
  13. //% END
  14. //% RESIZING_LAYOUT_BODY
  15. native static void onApplyInsets(
  16. int sys_left, int sys_top, int sys_right, int sys_bottom,
  17. int ime_left, int ime_top, int ime_right, int ime_bottom
  18. );
  19. //% END
  20. //% RESIZING_LAYOUT_ON_APPLY_WINDOW_INSETS
  21. {
  22. Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
  23. Insets sysInsets = insets.getInsets(WindowInsets.Type.systemBars());
  24. // Screen: (1440, 3064)
  25. // IME height: 1056
  26. // Sys insets: (0, 152, 0, 135)
  27. onApplyInsets(
  28. sysInsets.left, sysInsets.top, sysInsets.right, sysInsets.bottom,
  29. imeInsets.left, imeInsets.top, imeInsets.right, imeInsets.bottom
  30. );
  31. }
  32. // Workaround for Java error due to remaining body.
  33. // We handle the insets in our app directly.
  34. if (true)
  35. return insets;
  36. //% END
  37. //% MAIN_ACTIVITY_BODY
  38. // GameTextInput native bridge functions (following official Android pattern)
  39. native void setInputConnectionNative(textinput.InputConnection c);
  40. native void onTextInputEventNative(textinput.State softKeyboardEvent);
  41. // GameTextInput InputConnection reference (public for QuadSurface access)
  42. public textinput.InputConnection gameTextInputInputConnection;
  43. public String getAppDataPath() {
  44. return getApplicationContext().getDataDir().getAbsolutePath();
  45. }
  46. public String getExternalStoragePath() {
  47. return getApplicationContext().getExternalFilesDir(null).getAbsolutePath();
  48. }
  49. public int getKeyboardHeight() {
  50. WindowInsets windowInsets = view.getRootWindowInsets();
  51. if (windowInsets == null) {
  52. return 0;
  53. }
  54. Insets imeInsets = windowInsets.getInsets(WindowInsets.Type.ime());
  55. Insets navInsets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
  56. return Math.max(0, imeInsets.bottom - navInsets.bottom);
  57. }
  58. public float getScreenDensity() {
  59. return getResources().getDisplayMetrics().density;
  60. }
  61. public boolean isImeVisible() {
  62. View decorView = getWindow().getDecorView();
  63. WindowInsets insets = decorView.getRootWindowInsets();
  64. Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
  65. if (imeInsets == null)
  66. return false;
  67. return insets.isVisible(Type.ime());
  68. }
  69. public VideoDecoder createVideoDecoder() {
  70. VideoDecoder decoder = new VideoDecoder();
  71. decoder.setContext(this);
  72. return decoder;
  73. }
  74. //% END
  75. //% MAIN_ACTIVITY_ON_CREATE
  76. //view.setFocusable(false);
  77. //view.setFocusableInTouchMode(false);
  78. //view.clearFocus();
  79. // Start a foreground service so the app stays awake
  80. Intent serviceIntent = new Intent(this, ForegroundService.class);
  81. startForegroundService(serviceIntent);
  82. //% END
  83. //% QUAD_SURFACE_ON_CREATE_INPUT_CONNECTION
  84. // Get reference to MainActivity
  85. if (getContext() == null)
  86. Log.i("darkfi", "getCTX (on creat) is nulllll!!!!!!!!!!!!!!!!!!");
  87. MainActivity mainActivity = (MainActivity)getContext();
  88. android.util.Log.d("darkfi", "onCreateInputConnection called");
  89. // Create InputConnection if it doesn't exist yet
  90. if (mainActivity.gameTextInputInputConnection == null) {
  91. android.util.Log.d("darkfi", "Creating new InputConnection");
  92. // Create InputConnection with Context (from QuadSurface)
  93. android.view.inputmethod.EditorInfo editorInfo = new android.view.inputmethod.EditorInfo();
  94. editorInfo.inputType = android.text.InputType.TYPE_CLASS_TEXT |
  95. android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
  96. editorInfo.imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_FULLSCREEN;
  97. if (mainActivity == null)
  98. Log.i("darkfi", "mainact is NULLLL");
  99. mainActivity.gameTextInputInputConnection = new textinput.InputConnection(
  100. getContext(),
  101. this,
  102. new textinput.Settings(editorInfo, true)
  103. );
  104. // Pass the InputConnection to native GameTextInput library
  105. android.util.Log.d("darkfi", "InputConnection created and passed to native");
  106. mainActivity.setInputConnectionNative(mainActivity.gameTextInputInputConnection);
  107. } else {
  108. android.util.Log.d("darkfi", "Reusing existing InputConnection");
  109. }
  110. // Set the listener to receive IME state changes
  111. mainActivity.gameTextInputInputConnection.setListener(new textinput.Listener() {
  112. @Override
  113. public void stateChanged(textinput.State newState, boolean dismissed) {
  114. // Called when the IME sends new text state
  115. // Forward to native code which triggers Rust callback
  116. android.util.Log.d("darkfi", "stateChanged: text=" + newState.toString());
  117. mainActivity.onTextInputEventNative(newState);
  118. }
  119. @Override
  120. public void onImeInsetsChanged(androidx.core.graphics.Insets insets) {
  121. // Called when IME insets change (e.g., keyboard height changes)
  122. // Optional: can be used for dynamic layout adjustment
  123. }
  124. @Override
  125. public void onSoftwareKeyboardVisibilityChanged(boolean visible) {
  126. // Called when keyboard is shown or hidden
  127. android.util.Log.d("darkfi", "onSoftwareKeyboardVisibilityChanged: " + visible);
  128. }
  129. @Override
  130. public void onEditorAction(int actionCode) {
  131. // Called when user presses action button (Done, Next, etc.)
  132. // Optional: handle specific editor actions
  133. }
  134. });
  135. // Copy EditorInfo from GameTextInput to configure IME
  136. if (outAttrs != null) {
  137. textinput.GameTextInput.copyEditorInfo(
  138. mainActivity.gameTextInputInputConnection.getEditorInfo(),
  139. outAttrs
  140. );
  141. }
  142. // Return the GameTextInput InputConnection to IME
  143. if (true) return mainActivity.gameTextInputInputConnection;
  144. return mainActivity.gameTextInputInputConnection;
  145. //% END