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.Surface;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowInsetsController;
import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@@ -132,6 +134,70 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
setPointerIcon(pointerIcon); 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) { private void dispatchMotionEvent(MotionEvent event) {
for (int j = 0; j < event.getHistorySize(); j++) { for (int j = 0; j < event.getHistorySize(); j++) {
long time = event.getHistoricalEventTime(j); long time = event.getHistoricalEventTime(j);
+41 -1
View File
@@ -42,7 +42,9 @@ import "C"
import ( import (
"errors" "errors"
"fmt" "fmt"
"gioui.org/internal/f32color"
"image" "image"
"image/color"
"reflect" "reflect"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
@@ -83,6 +85,8 @@ type window struct {
// re-creates our Activity. // re-creates our Activity.
type windowState struct { type windowState struct {
cursor *pointer.CursorName cursor *pointer.CursorName
navigationColor *color.NRGBA
statusColor *color.NRGBA
} }
// gioView hold cached JNI methods for GioView. // gioView hold cached JNI methods for GioView.
@@ -94,6 +98,8 @@ var gioView struct {
hideTextInput C.jmethodID hideTextInput C.jmethodID
postFrameCallback C.jmethodID postFrameCallback C.jmethodID
setCursor C.jmethodID setCursor C.jmethodID
setNavigationColor C.jmethodID
setStatusColor C.jmethodID
} }
// ViewEvent is sent whenever the Window's underlying Android view // 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.hideTextInput = getMethodID(env, class, "hideTextInput", "()V")
m.postFrameCallback = getMethodID(env, class, "postFrameCallback", "()V") m.postFrameCallback = getMethodID(env, class, "postFrameCallback", "()V")
m.setCursor = getMethodID(env, class, "setCursor", "(I)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) view = C.gio_jni_NewGlobalRef(env, view)
wopts := <-mainWindow.out 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) handle := C.jlong(view)
views[handle] = w views[handle] = w
w.loadConfig(env, class) w.loadConfig(env, class)
w.Option(wopts.opts)
applyStateDiff(env, view, windowState{}, w.state) applyStateDiff(env, view, windowState{}, w.state)
w.setStage(system.StagePaused) w.setStage(system.StagePaused)
w.callbacks.Event(ViewEvent{View: uintptr(view)}) 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) { func (w *window) SetCursor(name pointer.CursorName) {
w.setState(func(state *windowState) { 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 { if state.cursor != nil && old.cursor != state.cursor {
setCursor(env, view, *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) { 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)) 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. // Close the window. Not implemented for Android.
func (w *window) Close() {} func (w *window) Close() {}
+20 -1
View File
@@ -3,7 +3,10 @@
package wm package wm
import ( import (
"fmt"
"gioui.org/internal/f32color"
"image" "image"
"image/color"
"strings" "strings"
"sync" "sync"
"syscall/js" "syscall/js"
@@ -22,6 +25,7 @@ import (
type window struct { type window struct {
window js.Value window js.Value
document js.Value document js.Value
head js.Value
clipboard js.Value clipboard js.Value
cnv js.Value cnv js.Value
tarea js.Value tarea js.Value
@@ -61,6 +65,7 @@ func NewWindow(win Callbacks, opts *Options) error {
document: doc, document: doc,
tarea: tarea, tarea: tarea,
window: js.Global().Get("window"), window: js.Global().Get("window"),
head: doc.Get("head"),
clipboard: js.Global().Get("navigator").Get("clipboard"), clipboard: js.Global().Get("navigator").Get("clipboard"),
} }
w.requestAnimationFrame = w.window.Get("requestAnimationFrame") w.requestAnimationFrame = w.window.Get("requestAnimationFrame")
@@ -486,6 +491,9 @@ func (w *window) Option(opts *Options) {
if o := opts.WindowMode; o != nil { if o := opts.WindowMode; o != nil {
w.windowMode(*o) w.windowMode(*o)
} }
if o := opts.NavigationColor; o != nil {
w.navigationColor(*o)
}
} }
func (w *window) SetCursor(name pointer.CursorName) { 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) { func (w *window) windowMode(mode WindowMode) {
switch mode { switch mode {
case Windowed: case Windowed:
if fs := w.document.Get("fullscreenElement"); !fs.Truthy() { if !w.document.Get("fullscreenElement").Truthy() {
return // Browser is already Windowed. return // Browser is already Windowed.
} }
if !w.document.Get("exitFullscreen").Truthy() { 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() { func Main() {
select {} select {}
} }
+3
View File
@@ -6,6 +6,7 @@ package wm
import ( import (
"errors" "errors"
"image/color"
"gioui.org/gpu" "gioui.org/gpu"
"gioui.org/io/event" "gioui.org/io/event"
@@ -25,6 +26,8 @@ type Options struct {
MaxSize *Size MaxSize *Size
Title *string Title *string
WindowMode *WindowMode WindowMode *WindowMode
StatusColor *color.NRGBA
NavigationColor *color.NRGBA
} }
type WindowMode uint8 type WindowMode uint8
+15
View File
@@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"image" "image"
"image/color"
"time" "time"
"gioui.org/io/event" "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() {} func (driverEvent) ImplementsEvent() {}