From d51d8b46c3c7f9c695be344e2a9fb681995f74d1 Mon Sep 17 00:00:00 2001 From: Inkeliz Date: Fri, 23 Apr 2021 18:21:58 +0100 Subject: [PATCH] app, app/internal: [wasm,android] new Option to set Orientation Signed-off-by: Inkeliz --- app/internal/wm/GioView.java | 7 +++++++ app/internal/wm/os_android.go | 28 ++++++++++++++++++++++++++++ app/internal/wm/os_js.go | 22 ++++++++++++++++++++++ app/internal/wm/window.go | 9 +++++++++ app/window.go | 20 +++++++++++++++++++- 5 files changed, 85 insertions(+), 1 deletion(-) diff --git a/app/internal/wm/GioView.java b/app/internal/wm/GioView.java index 356773c5..4dc842e4 100644 --- a/app/internal/wm/GioView.java +++ b/app/internal/wm/GioView.java @@ -134,6 +134,13 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal setPointerIcon(pointerIcon); } + private void setOrientation(int id, int fallback) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + id = fallback; + } + ((Activity) this.getContext()).setRequestedOrientation(id); + } + private enum Bar { NAVIGATION, STATUS, diff --git a/app/internal/wm/os_android.go b/app/internal/wm/os_android.go index 62f4d61b..59a53e72 100644 --- a/app/internal/wm/os_android.go +++ b/app/internal/wm/os_android.go @@ -85,6 +85,7 @@ type window struct { // re-creates our Activity. type windowState struct { cursor *pointer.CursorName + orientation *Orientation navigationColor *color.NRGBA statusColor *color.NRGBA } @@ -98,6 +99,7 @@ var gioView struct { hideTextInput C.jmethodID postFrameCallback C.jmethodID setCursor C.jmethodID + setOrientation C.jmethodID setNavigationColor C.jmethodID setStatusColor C.jmethodID } @@ -226,6 +228,7 @@ 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.setOrientation = getMethodID(env, class, "setOrientation", "(II)V") m.setNavigationColor = getMethodID(env, class, "setNavigationColor", "(II)V") m.setStatusColor = getMethodID(env, class, "setStatusColor", "(II)V") }) @@ -686,6 +689,11 @@ func (w *window) ReadClipboard() { } func (w *window) Option(opts *Options) { + if o := opts.Orientation; o != nil { + w.setState(func(state *windowState) { + state.orientation = o + }) + } if o := opts.NavigationColor; o != nil { w.setState(func(state *windowState) { state.navigationColor = o @@ -723,6 +731,9 @@ 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.orientation != nil && old.orientation != state.orientation { + setOrientation(env, view, *state.orientation) + } if state.navigationColor != nil && old.navigationColor != state.navigationColor { setNavigationColor(env, view, *state.navigationColor) } @@ -754,6 +765,23 @@ func setCursor(env *C.JNIEnv, view C.jobject, name pointer.CursorName) { callVoidMethod(env, view, gioView.setCursor, jvalue(curID)) } +func setOrientation(env *C.JNIEnv, view C.jobject, mode Orientation) { + var ( + id int + idFallback int // Used only for SDK 17 or older. + ) + // Constants defined at https://developer.android.com/reference/android/content/pm/ActivityInfo. + switch mode { + case AnyOrientation: + id, idFallback = 2, 2 // SCREEN_ORIENTATION_USER + case LandscapeOrientation: + id, idFallback = 11, 0 // SCREEN_ORIENTATION_USER_LANDSCAPE (or SCREEN_ORIENTATION_LANDSCAPE) + case PortraitOrientation: + id, idFallback = 12, 1 // SCREEN_ORIENTATION_USER_PORTRAIT (or SCREEN_ORIENTATION_PORTRAIT) + } + callVoidMethod(env, view, gioView.setOrientation, jvalue(id), jvalue(idFallback)) +} + 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)), diff --git a/app/internal/wm/os_js.go b/app/internal/wm/os_js.go index 85bd2936..3f7c6bdc 100644 --- a/app/internal/wm/os_js.go +++ b/app/internal/wm/os_js.go @@ -35,6 +35,7 @@ type window struct { requestAnimationFrame js.Value browserHistory js.Value visualViewport js.Value + screenOrientation js.Value cleanfuncs []func() touches []js.Value composing bool @@ -74,6 +75,9 @@ func NewWindow(win Callbacks, opts *Options) error { if w.visualViewport.IsUndefined() { w.visualViewport = w.window } + if screen := w.window.Get("screen"); screen.Truthy() { + w.screenOrientation = screen.Get("orientation") + } w.chanAnimation = make(chan struct{}, 1) w.chanRedraw = make(chan struct{}, 1) w.redraw = w.funcOf(func(this js.Value, args []js.Value) interface{} { @@ -494,6 +498,9 @@ func (w *window) Option(opts *Options) { if o := opts.NavigationColor; o != nil { w.navigationColor(*o) } + if o := opts.Orientation; o != nil { + w.orientation(*o) + } } func (w *window) SetCursor(name pointer.CursorName) { @@ -591,6 +598,21 @@ func (w *window) windowMode(mode WindowMode) { } } +func (w *window) orientation(mode Orientation) { + if j := w.screenOrientation; !j.Truthy() || !j.Get("unlock").Truthy() || !j.Get("lock").Truthy() { + return // Browser don't support Screen Orientation API. + } + + switch mode { + case AnyOrientation: + w.screenOrientation.Call("unlock") + case LandscapeOrientation: + w.screenOrientation.Call("lock", "landscape").Call("then", w.redraw) + case PortraitOrientation: + w.screenOrientation.Call("lock", "portrait").Call("then", w.redraw) + } +} + func (w *window) navigationColor(c color.NRGBA) { theme := w.head.Call("querySelector", `meta[name="theme-color"]`) if !theme.Truthy() { diff --git a/app/internal/wm/window.go b/app/internal/wm/window.go index 1cfb79af..2801824c 100644 --- a/app/internal/wm/window.go +++ b/app/internal/wm/window.go @@ -28,6 +28,7 @@ type Options struct { WindowMode *WindowMode StatusColor *color.NRGBA NavigationColor *color.NRGBA + Orientation *Orientation } type WindowMode uint8 @@ -37,6 +38,14 @@ const ( Fullscreen ) +type Orientation uint8 + +const ( + AnyOrientation Orientation = iota + LandscapeOrientation + PortraitOrientation +) + type FrameEvent struct { system.FrameEvent diff --git a/app/window.go b/app/window.go index f7809c99..8740f5b5 100644 --- a/app/window.go +++ b/app/window.go @@ -464,13 +464,31 @@ var ( // windowMode sets the window mode. // -// Supported platforms are macOS, X11 and Windows. +// Supported platforms are macOS, X11, Windows and JS. func windowMode(mode wm.WindowMode) Option { return func(opts *wm.Options) { opts.WindowMode = &mode } } +var ( + // AnyOrientation allows the window to be freely orientated. + AnyOrientation = orientation(wm.AnyOrientation) + // LandscapeOrientation constrains the window to landscape orientations. + LandscapeOrientation = orientation(wm.LandscapeOrientation) + // PortraitOrientation constrains the window to portrait orientations. + PortraitOrientation = orientation(wm.PortraitOrientation) +) + +// orientation sets the orientation of the app. +// +// Supported platforms are Android and JS. +func orientation(mode wm.Orientation) Option { + return func(opts *wm.Options) { + opts.Orientation = &mode + } +} + // Title sets the title of the wm. func Title(t string) Option { return func(opts *wm.Options) {