MainActivity.java 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //% IMPORTS
  2. import android.view.ViewGroup;
  3. import android.text.Editable;
  4. import android.text.Spannable;
  5. import android.text.SpanWatcher;
  6. import android.text.Spanned;
  7. import android.text.TextWatcher;
  8. import android.widget.EditText;
  9. import android.widget.TextView;
  10. import android.view.inputmethod.BaseInputConnection;
  11. import android.view.WindowInsets.Type;
  12. import java.util.HashMap;
  13. import autosuggest.InvisibleInputView;
  14. import autosuggest.CustomInputConnection;
  15. import videodecode.VideoDecoder;
  16. //% END
  17. //% RESIZING_LAYOUT_BODY
  18. native static void onApplyInsets(
  19. int sys_left, int sys_top, int sys_right, int sys_bottom,
  20. int ime_left, int ime_top, int ime_right, int ime_bottom
  21. );
  22. //% END
  23. //% RESIZING_LAYOUT_ON_APPLY_WINDOW_INSETS
  24. {
  25. Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
  26. Insets sysInsets = insets.getInsets(WindowInsets.Type.systemBars());
  27. // Screen: (1440, 3064)
  28. // IME height: 1056
  29. // Sys insets: (0, 152, 0, 135)
  30. onApplyInsets(
  31. sysInsets.left, sysInsets.top, sysInsets.right, sysInsets.bottom,
  32. imeInsets.left, imeInsets.top, imeInsets.right, imeInsets.bottom
  33. );
  34. }
  35. // Workaround for Java error due to remaining body.
  36. // We handle the insets in our app directly.
  37. if (true)
  38. return insets;
  39. //% END
  40. //% MAIN_ACTIVITY_BODY
  41. private ViewGroup rootView;
  42. private HashMap<Integer, InvisibleInputView> editors;
  43. native static void onInitEdit(int id);
  44. public void createComposer(final int id) {
  45. Log.d("darkfi", "createComposer() -> " + id);
  46. final InvisibleInputView iv = new InvisibleInputView(this, id);
  47. editors.put(id, iv);
  48. runOnUiThread(new Runnable() {
  49. @Override
  50. public void run() {
  51. rootView.addView(iv);
  52. iv.clearFocus();
  53. onInitEdit(id);
  54. }
  55. });
  56. }
  57. private InputMethodManager getIMM() {
  58. return (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
  59. }
  60. public boolean focus(final int id) {
  61. final InvisibleInputView iv = editors.get(id);
  62. if (iv == null) {
  63. return false;
  64. }
  65. runOnUiThread(new Runnable() {
  66. @Override
  67. public void run() {
  68. boolean isFocused = iv.requestFocus();
  69. // Just Android things ;)
  70. if (!isFocused) {
  71. Log.w("darkfi", "error requesting focus for id=" + id + ": " + iv);
  72. }
  73. getIMM().showSoftInput(iv, InputMethodManager.SHOW_IMPLICIT);
  74. }
  75. });
  76. return true;
  77. }
  78. public boolean unfocus(final int id) {
  79. final InvisibleInputView iv = editors.get(id);
  80. if (iv == null) {
  81. return false;
  82. }
  83. runOnUiThread(new Runnable() {
  84. @Override
  85. public void run() {
  86. iv.clearFocus();
  87. getIMM().hideSoftInputFromWindow(iv.getWindowToken(), 0);
  88. }
  89. });
  90. return true;
  91. }
  92. /*
  93. public CustomInputConnection getInputConnect(int id) {
  94. InvisibleInputView iv = editors.get(id);
  95. if (iv == null) {
  96. return null;
  97. }
  98. return iv.inputConnection;
  99. }
  100. */
  101. public InvisibleInputView getInputView(int id) {
  102. return editors.get(id);
  103. }
  104. public boolean setText(int id, String txt) {
  105. //Log.d("darkfi", "setText(" + id + ", " + txt + ")");
  106. InvisibleInputView iv = editors.get(id);
  107. if (iv == null) {
  108. return false;
  109. }
  110. // If inputConnection is not yet ready, then setup the editable directly.
  111. if (iv.inputConnection == null) {
  112. iv.setEditableText(txt);
  113. return true;
  114. }
  115. // Maybe do this on the UI thread?
  116. iv.inputConnection.setEditableText(txt, txt.length(), txt.length(), 0, 0);
  117. return true;
  118. }
  119. public boolean setSelection(int id, int start, int end) {
  120. InvisibleInputView iv = editors.get(id);
  121. if (iv == null) {
  122. return false;
  123. }
  124. // If inputConnection is not yet ready, then setup the sel directly.
  125. if (iv.inputConnection == null) {
  126. iv.setSelection(start, end);
  127. return true;
  128. }
  129. iv.inputConnection.beginBatchEdit();
  130. // Not sure if this is needed
  131. //if (start != end)
  132. // iv.inputConnection.finishComposingText();
  133. iv.inputConnection.setSelection(start, end);
  134. iv.inputConnection.endBatchEdit();
  135. return true;
  136. }
  137. public boolean commitText(int id, String txt) {
  138. //Log.d("darkfi", "setText(" + id + ", " + txt + ")");
  139. InvisibleInputView iv = editors.get(id);
  140. if (iv == null) {
  141. return false;
  142. }
  143. if (iv.inputConnection == null) {
  144. return false;
  145. }
  146. iv.inputConnection.beginBatchEdit();
  147. iv.inputConnection.finishComposingText();
  148. iv.inputConnection.commitText(txt, 1);
  149. iv.inputConnection.endBatchEdit();
  150. return true;
  151. }
  152. /*
  153. // Editable string with the spans displayed inline
  154. public String getDebugEditableStr() {
  155. String edit = view.inputConnection.debugEditableStr();
  156. Log.d("darkfi", "getDebugEditableStr() -> " + edit);
  157. return edit;
  158. }
  159. */
  160. public String getAppDataPath() {
  161. return getApplicationContext().getDataDir().getAbsolutePath();
  162. }
  163. public String getExternalStoragePath() {
  164. return getApplicationContext().getExternalFilesDir(null).getAbsolutePath();
  165. }
  166. public int getKeyboardHeight() {
  167. WindowInsets windowInsets = view.getRootWindowInsets();
  168. if (windowInsets == null) {
  169. return 0;
  170. }
  171. Insets imeInsets = windowInsets.getInsets(WindowInsets.Type.ime());
  172. Insets navInsets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
  173. return Math.max(0, imeInsets.bottom - navInsets.bottom);
  174. }
  175. public float getScreenDensity() {
  176. return getResources().getDisplayMetrics().density;
  177. }
  178. public boolean isImeVisible() {
  179. View decorView = getWindow().getDecorView();
  180. WindowInsets insets = decorView.getRootWindowInsets();
  181. Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
  182. if (imeInsets == null)
  183. return false;
  184. return insets.isVisible(Type.ime());
  185. }
  186. public VideoDecoder createVideoDecoder() {
  187. VideoDecoder decoder = new VideoDecoder();
  188. decoder.setContext(this);
  189. return decoder;
  190. }
  191. //% END
  192. //% MAIN_ACTIVITY_ON_CREATE
  193. rootView = layout;
  194. editors = new HashMap<>();
  195. view.setFocusable(false);
  196. view.setFocusableInTouchMode(false);
  197. view.clearFocus();
  198. // Start a foreground service so the app stays awake
  199. Intent serviceIntent = new Intent(this, ForegroundService.class);
  200. startForegroundService(serviceIntent);
  201. //% END