mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 15:45:38 +00:00
fc55c6ee5c
And add CommandBack for the Android back button. Signed-off-by: Elias Naur <mail@eliasnaur.com>
196 lines
5.2 KiB
Java
196 lines
5.2 KiB
Java
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package org.gioui;
|
|
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import android.os.Handler;
|
|
import android.util.AttributeSet;
|
|
import android.text.Editable;
|
|
import android.view.Choreographer;
|
|
import android.view.KeyCharacterMap;
|
|
import android.view.KeyEvent;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.Surface;
|
|
import android.view.SurfaceView;
|
|
import android.view.SurfaceHolder;
|
|
import android.view.inputmethod.BaseInputConnection;
|
|
import android.view.inputmethod.InputConnection;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.view.inputmethod.EditorInfo;
|
|
|
|
public class GioView extends SurfaceView implements Choreographer.FrameCallback {
|
|
private final SurfaceHolder.Callback callbacks;
|
|
private final InputMethodManager imm;
|
|
private final Handler handler;
|
|
private long nhandle;
|
|
|
|
public GioView(Context context) {
|
|
this(context, null);
|
|
}
|
|
|
|
public GioView(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
handler = new Handler();
|
|
imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
setFocusable(true);
|
|
setFocusableInTouchMode(true);
|
|
callbacks = new SurfaceHolder.Callback() {
|
|
@Override public void surfaceCreated(SurfaceHolder holder) {
|
|
// Ignore; surfaceChanged is guaranteed to be called immediately after this.
|
|
}
|
|
@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
|
onSurfaceChanged(nhandle, getHolder().getSurface());
|
|
}
|
|
@Override public void surfaceDestroyed(SurfaceHolder holder) {
|
|
onSurfaceDestroyed(nhandle);
|
|
}
|
|
};
|
|
getHolder().addCallback(callbacks);
|
|
nhandle = onCreateView(this);
|
|
}
|
|
|
|
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), event.getEventTime());
|
|
return false;
|
|
}
|
|
|
|
@Override public boolean onTouchEvent(MotionEvent event) {
|
|
// Ask for unbuffered events. Flutter and Chrome does it
|
|
// so I assume its good for us as well.
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
requestUnbufferedDispatch(event);
|
|
}
|
|
|
|
for (int j = 0; j < event.getHistorySize(); j++) {
|
|
long time = event.getHistoricalEventTime(j);
|
|
for (int i = 0; i < event.getPointerCount(); i++) {
|
|
onTouchEvent(
|
|
nhandle,
|
|
event.ACTION_MOVE,
|
|
event.getPointerId(i),
|
|
event.getToolType(i),
|
|
event.getHistoricalX(i, j),
|
|
event.getHistoricalY(i, j),
|
|
time);
|
|
}
|
|
}
|
|
int act = event.getActionMasked();
|
|
int idx = event.getActionIndex();
|
|
for (int i = 0; i < event.getPointerCount(); i++) {
|
|
int pact = event.ACTION_MOVE;
|
|
if (i == idx) {
|
|
pact = act;
|
|
}
|
|
onTouchEvent(
|
|
nhandle,
|
|
act,
|
|
event.getPointerId(i),
|
|
event.getToolType(i),
|
|
event.getX(i),
|
|
event.getY(i),
|
|
event.getEventTime());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
|
return new InputConnection(this);
|
|
}
|
|
|
|
void showTextInput() {
|
|
post(new Runnable() {
|
|
@Override public void run() {
|
|
GioView.this.requestFocus();
|
|
imm.showSoftInput(GioView.this, 0);
|
|
}
|
|
});
|
|
}
|
|
|
|
void hideTextInput() {
|
|
post(new Runnable() {
|
|
@Override public void run() {
|
|
imm.hideSoftInputFromWindow(getWindowToken(), 0);
|
|
}
|
|
});
|
|
}
|
|
|
|
void postFrameCallbackOnMainThread() {
|
|
handler.post(new Runnable() {
|
|
@Override public void run() {
|
|
postFrameCallback();
|
|
}
|
|
});
|
|
}
|
|
|
|
void postFrameCallback() {
|
|
Choreographer.getInstance().removeFrameCallback(this);
|
|
Choreographer.getInstance().postFrameCallback(this);
|
|
}
|
|
|
|
@Override public void doFrame(long nanos) {
|
|
onFrameCallback(nhandle, nanos);
|
|
}
|
|
|
|
int getDensity() {
|
|
return getResources().getDisplayMetrics().densityDpi;
|
|
}
|
|
|
|
float getFontScale() {
|
|
return getResources().getConfiguration().fontScale;
|
|
}
|
|
|
|
void start() {
|
|
onStartView(nhandle);
|
|
}
|
|
|
|
void stop() {
|
|
onStopView(nhandle);
|
|
}
|
|
|
|
void destroy() {
|
|
getHolder().removeCallback(callbacks);
|
|
onDestroyView(nhandle);
|
|
nhandle = 0;
|
|
}
|
|
|
|
void configurationChanged() {
|
|
onConfigurationChanged(nhandle);
|
|
}
|
|
|
|
void lowMemory() {
|
|
onLowMemory();
|
|
}
|
|
|
|
boolean backPressed() {
|
|
return onBack(nhandle);
|
|
}
|
|
|
|
static private native long onCreateView(GioView view);
|
|
static private native void onDestroyView(long handle);
|
|
static private native void onStartView(long handle);
|
|
static private native void onStopView(long handle);
|
|
static private native void onSurfaceDestroyed(long handle);
|
|
static private native void onSurfaceChanged(long handle, Surface surface);
|
|
static private native void onConfigurationChanged(long handle);
|
|
static private native void onLowMemory();
|
|
static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, long time);
|
|
static private native void onKeyEvent(long handle, int code, int character, long time);
|
|
static private native void onFrameCallback(long handle, long nanos);
|
|
static private native boolean onBack(long handle);
|
|
|
|
private static class InputConnection extends BaseInputConnection {
|
|
private final Editable editable;
|
|
|
|
InputConnection(View view) {
|
|
super(view, true);
|
|
editable = Editable.Factory.getInstance().newEditable("");
|
|
}
|
|
|
|
@Override public Editable getEditable() {
|
|
return editable;
|
|
}
|
|
}
|
|
}
|