Skip to content

Commit e536831

Browse files
author
Chris Warren-Smith
committed
ANDROID: implemented support for editing with the system keypad
- Fixes for Pixel 9/Android 16
1 parent d566fde commit e536831

File tree

5 files changed

+60
-18
lines changed

5 files changed

+60
-18
lines changed

src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,15 @@
3939
import android.window.OnBackInvokedCallback;
4040
import android.window.OnBackInvokedDispatcher;
4141

42+
import androidx.annotation.NonNull;
4243
import androidx.annotation.RequiresPermission;
4344
import androidx.core.app.ActivityCompat;
4445
import androidx.core.content.ContextCompat;
4546
import androidx.core.content.FileProvider;
47+
import androidx.core.graphics.Insets;
48+
import androidx.core.view.OnApplyWindowInsetsListener;
49+
import androidx.core.view.ViewCompat;
50+
import androidx.core.view.WindowInsetsCompat;
4651

4752
import java.io.BufferedReader;
4853
import java.io.BufferedWriter;
@@ -121,7 +126,7 @@ public class MainActivity extends NativeActivity {
121126
public static native boolean libraryMode();
122127
public static native void onActivityPaused(boolean paused);
123128
public static native void onBack();
124-
public static native void onResize(int width, int height);
129+
public static native void onResize(int width, int height, int imeState);
125130
public static native void onUnicodeChar(int ch);
126131
public static native boolean optionSelected(int index);
127132
public static native void runFile(String fileName);
@@ -429,6 +434,10 @@ public int getWindowHeight() {
429434
return rect.height();
430435
}
431436

437+
public boolean isInsetBasedOnResize() {
438+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA;
439+
}
440+
432441
public boolean isPredictiveBack() {
433442
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA;
434443
}
@@ -452,10 +461,11 @@ public boolean loadModules() {
452461
@Override
453462
public void onGlobalLayout() {
454463
super.onGlobalLayout();
455-
// find the visible coordinates of our view
456-
Rect rect = new Rect();
457-
findViewById(android.R.id.content).getWindowVisibleDisplayFrame(rect);
458-
onResize(rect.width(), rect.height());
464+
if (!isInsetBasedOnResize()) {
465+
Rect rect = new Rect();
466+
findViewById(android.R.id.content).getWindowVisibleDisplayFrame(rect);
467+
onResize(rect.width(), rect.height(), 0);
468+
}
459469
}
460470

461471
@Override
@@ -774,6 +784,7 @@ protected void onCreate(Bundle savedInstanceState) {
774784
setImmersiveMode();
775785
setupStorageEnvironment();
776786
setupPredictiveBack();
787+
setupInsetBaseOnResize();
777788
if (!libraryMode()) {
778789
processIntent();
779790
processSettings();
@@ -1063,14 +1074,40 @@ private void setImmersiveMode() {
10631074
}
10641075
}
10651076

1077+
/**
1078+
* onResize() handler for android 16+
1079+
*/
1080+
private void setupInsetBaseOnResize() {
1081+
if (isInsetBasedOnResize()) {
1082+
View view = getWindow().getDecorView();
1083+
ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() {
1084+
@NonNull
1085+
@Override
1086+
public WindowInsetsCompat onApplyWindowInsets(@NonNull View view, @NonNull WindowInsetsCompat insets) {
1087+
Log.d(TAG, "onApplyWindowInsets");
1088+
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
1089+
Insets navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
1090+
Insets ime = insets.getInsets(WindowInsetsCompat.Type.ime());
1091+
boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
1092+
view.setPadding(0, 0, navInsets.right, navInsets.bottom);
1093+
int bottomInset = Math.max(systemBars.bottom, ime.bottom);
1094+
int width = view.getWidth();
1095+
int height = view.getHeight() - systemBars.top - bottomInset;
1096+
onResize(width, height, imeVisible ? 1 : -1);
1097+
return insets;
1098+
}
1099+
});
1100+
view.post(() -> ViewCompat.requestApplyInsets(view));
1101+
}
1102+
}
1103+
10661104
//
10671105
// Hook into Predictive Back (Android 13+)
10681106
//
10691107
private void setupPredictiveBack() {
10701108
if (isPredictiveBack()) {
10711109
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
1072-
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
1073-
new OnBackInvokedCallback() {
1110+
OnBackInvokedDispatcher.PRIORITY_OVERLAY, new OnBackInvokedCallback() {
10741111
@Override
10751112
public void onBackInvoked() {
10761113
Log.d(TAG, "onBackInvoked");

src/platform/android/jni/editor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ void Runtime::editSource(strlib::String loadPath, bool restoreOnExit) {
130130
int h = _output->getHeight();
131131
int charWidth = _output->getCharWidth();
132132
int charHeight = _output->getCharHeight();
133-
int screenId = opt_ide == IDE_EXTERNAL ? SOURCE_SCREEN : FORM_SCREEN;
134-
int prevScreenId = _output->selectScreen(screenId);
133+
int prevScreenId = _output->selectScreen(FORM_SCREEN);
135134
TextEditInput *editWidget;
136135
if (_editor != nullptr) {
137136
editWidget = _editor;

src/platform/android/jni/runtime.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ extern "C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_s
219219
}
220220

221221
extern "C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_onResize
222-
(JNIEnv *env, jclass jclazz, jint width, jint height) {
222+
(JNIEnv *env, jclass jclazz, jint width, jint height, jint imeState) {
223223
if (runtime != nullptr && !runtime->isClosing() && runtime->isActive() && os_graphics) {
224-
runtime->onResize(width, height);
224+
runtime->onResize(width, height, imeState);
225225
}
226226
}
227227

@@ -258,7 +258,7 @@ extern "C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_c
258258

259259
void onContentRectChanged(ANativeActivity *activity, const ARect *rect) {
260260
logEntered();
261-
runtime->onResize(rect->right, rect->bottom);
261+
runtime->onResize(rect->right, rect->bottom, 0);
262262
}
263263

264264
jbyteArray newByteArray(JNIEnv *env, const char *str) {
@@ -619,7 +619,7 @@ void Runtime::loadConfig() {
619619
int height = getInteger("getWindowHeight");
620620
if (height != _graphics->getHeight()) {
621621
// height adjustment for bottom virtual navigation bar
622-
onResize(_graphics->getWidth(), height);
622+
onResize(_graphics->getWidth(), height, 0);
623623
}
624624

625625
_output->setTextColor(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
@@ -990,14 +990,18 @@ void Runtime::showKeypad(bool show) {
990990
_app->activity->vm->DetachCurrentThread();
991991
}
992992

993-
void Runtime::onResize(int width, int height) {
993+
void Runtime::onResize(int width, int height, int imeState) {
994994
logEntered();
995995
if (_graphics != nullptr) {
996996
int w = _graphics->getWidth();
997997
int h = _graphics->getHeight();
998998
if (w != width || h != height) {
999-
trace("Resized from %d %d to %d %d", w, h, width, height);
999+
trace("Resized from %d %d to %d %d [ime=%d]", w, h, width, height, imeState);
10001000
ALooper_acquire(_app->looper);
1001+
if (imeState != 0) {
1002+
// in android 16+ when resize also knows whether the ime (keypad) is active
1003+
_keypadActive = (imeState > 0);
1004+
}
10011005
_graphics->setSize(width, height);
10021006
auto *maEvent = new MAEvent();
10031007
maEvent->type = EVENT_TYPE_SCREEN_CHANGED;

src/platform/android/jni/runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct Runtime : public System {
7070
void showCursor(CursorType cursorType) override {}
7171
void showKeypad(bool show);
7272
void onPaused(bool paused) { if (_graphics != nullptr) _graphics->onPaused(paused); }
73-
void onResize(int w, int h);
73+
void onResize(int w, int h, int imeState);
7474
void onRunCompleted() override;
7575
void onUnicodeChar(int ch);
7676
void loadConfig();

src/ui/textedit.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,8 +2538,10 @@ void TextEditHelpWidget::layout(int x, int y, int w, int h) {
25382538
case kPopup:
25392539
_width = w - (_x + _xmargin);
25402540
_height = h - (_y + _ymargin);
2541-
_x = _xBase;
2542-
_y = _yBase;
2541+
#if !defined(_ANDROID)
2542+
_x = _xBase;
2543+
_y = _yBase;
2544+
#endif
25432545
}
25442546
}
25452547
}

0 commit comments

Comments
 (0)