app, app/internal: [wasm,android] new Option to change navigation/status color

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
This commit is contained in:
Inkeliz
2021-04-18 08:22:41 +01:00
committed by Elias Naur
parent 2296c80d28
commit 9dae29844c
5 changed files with 158 additions and 15 deletions
+66
View File
@@ -29,6 +29,8 @@ import android.view.WindowInsets;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowInsetsController;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -132,6 +134,70 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
setPointerIcon(pointerIcon);
}
private enum Bar {
NAVIGATION,
STATUS,
}
private void setBarColor(Bar t, int color, int luminance) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
Window window = ((Activity) this.getContext()).getWindow();
int insetsMask;
int viewMask;
switch (t) {
case STATUS:
insetsMask = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
viewMask = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
window.setStatusBarColor(color);
break;
case NAVIGATION:
insetsMask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
viewMask = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
window.setNavigationBarColor(color);
break;
default:
throw new RuntimeException("invalid bar type");
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
int flags = this.getSystemUiVisibility();
if (luminance > 128) {
flags |= viewMask;
} else {
flags &= ~viewMask;
}
this.setSystemUiVisibility(flags);
return;
}
WindowInsetsController insetsController = window.getInsetsController();
if (insetsController == null) {
return;
}
if (luminance > 128) {
insetsController.setSystemBarsAppearance(insetsMask, insetsMask);
} else {
insetsController.setSystemBarsAppearance(0, insetsMask);
}
}
private void setStatusColor(int color, int luminance) {
this.setBarColor(Bar.STATUS, color, luminance);
}
private void setNavigationColor(int color, int luminance) {
this.setBarColor(Bar.NAVIGATION, color, luminance);
}
private void dispatchMotionEvent(MotionEvent event) {
for (int j = 0; j < event.getHistorySize(); j++) {
long time = event.getHistoricalEventTime(j);
+49 -9
View File
@@ -42,7 +42,9 @@ import "C"
import (
"errors"
"fmt"
"gioui.org/internal/f32color"
"image"
"image/color"
"reflect"
"runtime"
"runtime/debug"
@@ -82,18 +84,22 @@ type window struct {
// windowState tracks the View or Activity specific state lost when Android
// re-creates our Activity.
type windowState struct {
cursor *pointer.CursorName
cursor *pointer.CursorName
navigationColor *color.NRGBA
statusColor *color.NRGBA
}
// gioView hold cached JNI methods for GioView.
var gioView struct {
once sync.Once
getDensity C.jmethodID
getFontScale C.jmethodID
showTextInput C.jmethodID
hideTextInput C.jmethodID
postFrameCallback C.jmethodID
setCursor C.jmethodID
once sync.Once
getDensity C.jmethodID
getFontScale C.jmethodID
showTextInput C.jmethodID
hideTextInput C.jmethodID
postFrameCallback C.jmethodID
setCursor C.jmethodID
setNavigationColor C.jmethodID
setStatusColor C.jmethodID
}
// ViewEvent is sent whenever the Window's underlying Android view
@@ -220,6 +226,8 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j
m.hideTextInput = getMethodID(env, class, "hideTextInput", "()V")
m.postFrameCallback = getMethodID(env, class, "postFrameCallback", "()V")
m.setCursor = getMethodID(env, class, "setCursor", "(I)V")
m.setNavigationColor = getMethodID(env, class, "setNavigationColor", "(II)V")
m.setStatusColor = getMethodID(env, class, "setStatusColor", "(II)V")
})
view = C.gio_jni_NewGlobalRef(env, view)
wopts := <-mainWindow.out
@@ -235,6 +243,7 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j
handle := C.jlong(view)
views[handle] = w
w.loadConfig(env, class)
w.Option(wopts.opts)
applyStateDiff(env, view, windowState{}, w.state)
w.setStage(system.StagePaused)
w.callbacks.Event(ViewEvent{View: uintptr(view)})
@@ -676,7 +685,18 @@ func (w *window) ReadClipboard() {
})
}
func (w *window) Option(opts *Options) {}
func (w *window) Option(opts *Options) {
if o := opts.NavigationColor; o != nil {
w.setState(func(state *windowState) {
state.navigationColor = o
})
}
if o := opts.StatusColor; o != nil {
w.setState(func(state *windowState) {
state.statusColor = o
})
}
}
func (w *window) SetCursor(name pointer.CursorName) {
w.setState(func(state *windowState) {
@@ -703,6 +723,12 @@ func applyStateDiff(env *C.JNIEnv, view C.jobject, old, state windowState) {
if state.cursor != nil && old.cursor != state.cursor {
setCursor(env, view, *state.cursor)
}
if state.navigationColor != nil && old.navigationColor != state.navigationColor {
setNavigationColor(env, view, *state.navigationColor)
}
if state.statusColor != nil && old.statusColor != state.statusColor {
setStatusColor(env, view, *state.statusColor)
}
}
func setCursor(env *C.JNIEnv, view C.jobject, name pointer.CursorName) {
@@ -728,6 +754,20 @@ func setCursor(env *C.JNIEnv, view C.jobject, name pointer.CursorName) {
callVoidMethod(env, view, gioView.setCursor, jvalue(curID))
}
func setStatusColor(env *C.JNIEnv, view C.jobject, color color.NRGBA) {
callVoidMethod(env, view, gioView.setStatusColor,
jvalue(uint32(color.A)<<24|uint32(color.R)<<16|uint32(color.G)<<8|uint32(color.B)),
jvalue(int(f32color.LinearFromSRGB(color).Luminance()*255)),
)
}
func setNavigationColor(env *C.JNIEnv, view C.jobject, color color.NRGBA) {
callVoidMethod(env, view, gioView.setNavigationColor,
jvalue(uint32(color.A)<<24|uint32(color.R)<<16|uint32(color.G)<<8|uint32(color.B)),
jvalue(int(f32color.LinearFromSRGB(color).Luminance()*255)),
)
}
// Close the window. Not implemented for Android.
func (w *window) Close() {}
+20 -1
View File
@@ -3,7 +3,10 @@
package wm
import (
"fmt"
"gioui.org/internal/f32color"
"image"
"image/color"
"strings"
"sync"
"syscall/js"
@@ -22,6 +25,7 @@ import (
type window struct {
window js.Value
document js.Value
head js.Value
clipboard js.Value
cnv js.Value
tarea js.Value
@@ -61,6 +65,7 @@ func NewWindow(win Callbacks, opts *Options) error {
document: doc,
tarea: tarea,
window: js.Global().Get("window"),
head: doc.Get("head"),
clipboard: js.Global().Get("navigator").Get("clipboard"),
}
w.requestAnimationFrame = w.window.Get("requestAnimationFrame")
@@ -486,6 +491,9 @@ func (w *window) Option(opts *Options) {
if o := opts.WindowMode; o != nil {
w.windowMode(*o)
}
if o := opts.NavigationColor; o != nil {
w.navigationColor(*o)
}
}
func (w *window) SetCursor(name pointer.CursorName) {
@@ -567,7 +575,7 @@ func (w *window) config() (int, int, system.Insets, unit.Metric) {
func (w *window) windowMode(mode WindowMode) {
switch mode {
case Windowed:
if fs := w.document.Get("fullscreenElement"); !fs.Truthy() {
if !w.document.Get("fullscreenElement").Truthy() {
return // Browser is already Windowed.
}
if !w.document.Get("exitFullscreen").Truthy() {
@@ -583,6 +591,17 @@ func (w *window) windowMode(mode WindowMode) {
}
}
func (w *window) navigationColor(c color.NRGBA) {
theme := w.head.Call("querySelector", `meta[name="theme-color"]`)
if !theme.Truthy() {
theme = w.document.Call("createElement", "meta")
theme.Set("name", "theme-color")
w.head.Call("appendChild", theme)
}
rgba := f32color.NRGBAToRGBA(c)
theme.Set("content", fmt.Sprintf("#%06X", []uint8{rgba.R, rgba.G, rgba.B}))
}
func Main() {
select {}
}
+8 -5
View File
@@ -6,6 +6,7 @@ package wm
import (
"errors"
"image/color"
"gioui.org/gpu"
"gioui.org/io/event"
@@ -20,11 +21,13 @@ type Size struct {
}
type Options struct {
Size *Size
MinSize *Size
MaxSize *Size
Title *string
WindowMode *WindowMode
Size *Size
MinSize *Size
MaxSize *Size
Title *string
WindowMode *WindowMode
StatusColor *color.NRGBA
NavigationColor *color.NRGBA
}
type WindowMode uint8
+15
View File
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"image"
"image/color"
"time"
"gioui.org/io/event"
@@ -525,4 +526,18 @@ func MinSize(w, h unit.Value) Option {
}
}
// StatusColor sets the color of the Android status bar.
func StatusColor(color color.NRGBA) Option {
return func(opts *wm.Options) {
opts.StatusColor = &color
}
}
// NavigationColor sets the color of the navigation bar on Android, or the address bar in browsers.
func NavigationColor(color color.NRGBA) Option {
return func(opts *wm.Options) {
opts.NavigationColor = &color
}
}
func (driverEvent) ImplementsEvent() {}