mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 08:55:35 +00:00
app: add RegisterFragment method on *Window for Android
RegisterFragment creates an instance of a Java class and registers it as a Fragment in the window's Context. Signed-off-by: Greg Pomerantz <gmp.gio@wow.st>
This commit is contained in:
committed by
Elias Naur
parent
ce76c2e996
commit
2ca2e5462f
@@ -9,13 +9,6 @@ import (
|
|||||||
"gioui.org/app/internal/window"
|
"gioui.org/app/internal/window"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handle window.Handle
|
|
||||||
|
|
||||||
// PlatformHandle returns the platform specific Handle.
|
|
||||||
func PlatformHandle() *Handle {
|
|
||||||
return (*Handle)(window.PlatformHandle)
|
|
||||||
}
|
|
||||||
|
|
||||||
// extraArgs contains extra arguments to append to
|
// extraArgs contains extra arguments to append to
|
||||||
// os.Args. The arguments are separated with |.
|
// os.Args. The arguments are separated with |.
|
||||||
// Useful for running programs on mobiles where the
|
// Useful for running programs on mobiles where the
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gioui.org/app/internal/window"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handle window.Handle
|
||||||
|
|
||||||
|
// PlatformHandle returns the Android platform-specific Handle.
|
||||||
|
func PlatformHandle() *Handle {
|
||||||
|
return (*Handle)(window.PlatformHandle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// androidDriver is an interface that allows the Window's run method
|
||||||
|
// to call the RegisterFragment method of the Android window driver.
|
||||||
|
type androidDriver interface {
|
||||||
|
RegisterFragment(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFragment constructs a Java instance of the specified class
|
||||||
|
// and registers it as a Fragment in the Context in which the View was
|
||||||
|
// created.
|
||||||
|
func (w *Window) RegisterFragment(del string) {
|
||||||
|
go func() {
|
||||||
|
w.driverFuncs <- func() {
|
||||||
|
d := w.driver.(androidDriver)
|
||||||
|
d.RegisterFragment(del)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
@@ -2,12 +2,21 @@
|
|||||||
|
|
||||||
package org.gioui;
|
package org.gioui;
|
||||||
|
|
||||||
|
import java.lang.Class;
|
||||||
|
import java.lang.IllegalAccessException;
|
||||||
|
import java.lang.InstantiationException;
|
||||||
|
import java.lang.ExceptionInInitializerError;
|
||||||
|
import java.lang.SecurityException;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
|
import android.app.FragmentTransaction;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.KeyCharacterMap;
|
import android.view.KeyCharacterMap;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@@ -57,11 +66,12 @@ public class GioView extends SurfaceView implements Choreographer.FrameCallback
|
|||||||
|
|
||||||
public GioView(Context context, AttributeSet attrs) {
|
public GioView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
|
handler = new Handler();
|
||||||
// Late initialization of the Go runtime to wait for a valid context.
|
// Late initialization of the Go runtime to wait for a valid context.
|
||||||
initialize(context.getApplicationContext());
|
initialize(context.getApplicationContext());
|
||||||
|
|
||||||
nhandle = onCreateView(this);
|
nhandle = onCreateView(this);
|
||||||
handler = new Handler();
|
|
||||||
imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
@@ -207,6 +217,35 @@ public class GioView extends SurfaceView implements Choreographer.FrameCallback
|
|||||||
return onBack(nhandle);
|
return onBack(nhandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerFragment(String del) {
|
||||||
|
final Class cls;
|
||||||
|
try {
|
||||||
|
cls = getContext().getClassLoader().loadClass(del);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("RegisterFragment: fragment class not found: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
final Fragment frag;
|
||||||
|
try {
|
||||||
|
frag = (Fragment)cls.newInstance();
|
||||||
|
} catch (IllegalAccessException | InstantiationException | ExceptionInInitializerError | SecurityException | ClassCastException e) {
|
||||||
|
throw new RuntimeException("RegisterFragment: error instantiating fragment: " + e.getMessage());
|
||||||
|
}
|
||||||
|
final FragmentManager fm;
|
||||||
|
try {
|
||||||
|
fm = ((Activity)getContext()).getFragmentManager();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new RuntimeException("RegisterFragment: cannot get fragment manager from View Context: " + e.getMessage());
|
||||||
|
}
|
||||||
|
FragmentTransaction ft = fm.beginTransaction();
|
||||||
|
ft.add(frag, del);
|
||||||
|
ft.commitNow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static private native long onCreateView(GioView view);
|
static private native long onCreateView(GioView view);
|
||||||
static private native void onDestroyView(long handle);
|
static private native void onDestroyView(long handle);
|
||||||
static private native void onStartView(long handle);
|
static private native void onStartView(long handle);
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
// +build !android
|
|
||||||
|
|
||||||
package window
|
|
||||||
|
|
||||||
var PlatformHandle *Handle
|
|
||||||
|
|
||||||
type Handle struct{}
|
|
||||||
@@ -166,3 +166,8 @@ void gio_jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes)
|
|||||||
jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr) {
|
jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr) {
|
||||||
return (*env)->GetArrayLength(env, arr);
|
return (*env)->GetArrayLength(env, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gio_jni_RegisterFragment(JNIEnv *env, jobject view, jmethodID mid, char* del) {
|
||||||
|
jstring jdel = (*env)->NewStringUTF(env, del);
|
||||||
|
(*env)->CallObjectMethod(env, view, mid, jdel);
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ type window struct {
|
|||||||
mhideTextInput C.jmethodID
|
mhideTextInput C.jmethodID
|
||||||
mpostFrameCallback C.jmethodID
|
mpostFrameCallback C.jmethodID
|
||||||
mpostFrameCallbackOnMainThread C.jmethodID
|
mpostFrameCallbackOnMainThread C.jmethodID
|
||||||
|
mRegisterFragment C.jmethodID
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataDirChan = make(chan string, 1)
|
var dataDirChan = make(chan string, 1)
|
||||||
@@ -119,6 +120,7 @@ func onCreateView(env *C.JNIEnv, class C.jclass, view C.jobject) C.jlong {
|
|||||||
mhideTextInput: jniGetMethodID(env, class, "hideTextInput", "()V"),
|
mhideTextInput: jniGetMethodID(env, class, "hideTextInput", "()V"),
|
||||||
mpostFrameCallback: jniGetMethodID(env, class, "postFrameCallback", "()V"),
|
mpostFrameCallback: jniGetMethodID(env, class, "postFrameCallback", "()V"),
|
||||||
mpostFrameCallbackOnMainThread: jniGetMethodID(env, class, "postFrameCallbackOnMainThread", "()V"),
|
mpostFrameCallbackOnMainThread: jniGetMethodID(env, class, "postFrameCallbackOnMainThread", "()V"),
|
||||||
|
mRegisterFragment: jniGetMethodID(env, class, "registerFragment", "(Ljava/lang/String;)V"),
|
||||||
}
|
}
|
||||||
wopts := <-mainWindow.out
|
wopts := <-mainWindow.out
|
||||||
w.callbacks = wopts.window
|
w.callbacks = wopts.window
|
||||||
@@ -443,6 +445,14 @@ func (w *window) ShowTextInput(show bool) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *window) RegisterFragment(del string) {
|
||||||
|
runInJVM(func(env *C.JNIEnv) {
|
||||||
|
cdel := C.CString(del)
|
||||||
|
defer C.free(unsafe.Pointer(cdel))
|
||||||
|
C.gio_jni_RegisterFragment(env, w.view, w.mRegisterFragment, cdel)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func Main() {
|
func Main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ __attribute__ ((visibility ("hidden"))) void gio_jni_CallVoidMethod_J(JNIEnv *en
|
|||||||
__attribute__ ((visibility ("hidden"))) jbyte *gio_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr);
|
__attribute__ ((visibility ("hidden"))) jbyte *gio_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr);
|
||||||
__attribute__ ((visibility ("hidden"))) void gio_jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes);
|
__attribute__ ((visibility ("hidden"))) void gio_jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *bytes);
|
||||||
__attribute__ ((visibility ("hidden"))) jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr);
|
__attribute__ ((visibility ("hidden"))) jsize gio_jni_GetArrayLength(JNIEnv *env, jbyteArray arr);
|
||||||
|
__attribute__ ((visibility ("hidden"))) void gio_jni_RegisterFragment(JNIEnv *env, jobject view, jmethodID mid, char* del);
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ type Window struct {
|
|||||||
driver window.Driver
|
driver window.Driver
|
||||||
gpu *gpu.GPU
|
gpu *gpu.GPU
|
||||||
|
|
||||||
|
// driverFuncs is a channel of functions to run when
|
||||||
|
// the Window has a valid driver.
|
||||||
|
driverFuncs chan func()
|
||||||
|
|
||||||
out chan event.Event
|
out chan event.Event
|
||||||
in chan event.Event
|
in chan event.Event
|
||||||
ack chan struct{}
|
ack chan struct{}
|
||||||
@@ -95,6 +99,7 @@ func NewWindow(options ...Option) *Window {
|
|||||||
invalidates: make(chan struct{}, 1),
|
invalidates: make(chan struct{}, 1),
|
||||||
frames: make(chan *op.Ops),
|
frames: make(chan *op.Ops),
|
||||||
frameAck: make(chan struct{}),
|
frameAck: make(chan struct{}),
|
||||||
|
driverFuncs: make(chan func()),
|
||||||
}
|
}
|
||||||
w.callbacks.w = w
|
w.callbacks.w = w
|
||||||
go w.run(opts)
|
go w.run(opts)
|
||||||
@@ -227,6 +232,10 @@ func (w *Window) run(opts *window.Options) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
|
var driverFuncs chan func() = nil
|
||||||
|
if w.driver != nil {
|
||||||
|
driverFuncs = w.driverFuncs
|
||||||
|
}
|
||||||
var timer <-chan time.Time
|
var timer <-chan time.Time
|
||||||
if w.delayedDraw != nil {
|
if w.delayedDraw != nil {
|
||||||
timer = w.delayedDraw.C
|
timer = w.delayedDraw.C
|
||||||
@@ -238,6 +247,8 @@ func (w *Window) run(opts *window.Options) {
|
|||||||
case <-w.invalidates:
|
case <-w.invalidates:
|
||||||
w.setNextFrame(time.Time{})
|
w.setNextFrame(time.Time{})
|
||||||
w.updateAnimation()
|
w.updateAnimation()
|
||||||
|
case f := <-driverFuncs:
|
||||||
|
f()
|
||||||
case e := <-w.in:
|
case e := <-w.in:
|
||||||
switch e2 := e.(type) {
|
switch e2 := e.(type) {
|
||||||
case system.StageEvent:
|
case system.StageEvent:
|
||||||
|
|||||||
Reference in New Issue
Block a user