diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 27698c4268..d2d6022c38 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -256,7 +256,16 @@ protected void onCreate(Bundle savedInstanceState) { protected void initializeWidgets() { mWindows = new Windows(this); - mWindows.setDelegate(this::attachToWindow); + mWindows.setDelegate(new Windows.Delegate() { + @Override + public void onFocusedWindowChanged(@NonNull WindowWidget aFocusedWindow, @Nullable WindowWidget aPrevFocusedWindow) { + attachToWindow(aFocusedWindow, aPrevFocusedWindow); + } + @Override + public void onWindowBorderChanged(@NonNull WindowWidget aChangeWindow) { + mKeyboard.proxifyLayerIfNeeded(mWindows.getCurrentWindows()); + } + }); // Create Browser navigation widget mNavigationBar = new NavigationBarWidget(this); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/KeyboardWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/KeyboardWidget.java index e3063501e8..c25c9df6b9 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/KeyboardWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/KeyboardWidget.java @@ -359,6 +359,23 @@ public void dismiss() { hideOverlays(); } + public void proxifyLayerIfNeeded(ArrayList aWindows) { + if (!SettingsStore.getInstance(getContext()).getLayersEnabled()) { + return; + } + boolean proxify = false; + for (WindowWidget window: aWindows) { + if (window.getPlacement().borderColor != 0) { + proxify = true; + break; + } + } + if (mWidgetPlacement.proxifyLayer != proxify) { + mWidgetPlacement.proxifyLayer = proxify; + mWidgetManager.updateWidget(this); + } + } + private void hideOverlays() { mPopupKeyboardView.setVisibility(View.GONE); mPopupKeyboardLayer.setVisibility(View.GONE); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UISurfaceTextureRenderer.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UISurfaceTextureRenderer.java index ed46e5ba48..43e3773dd3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UISurfaceTextureRenderer.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UISurfaceTextureRenderer.java @@ -43,6 +43,9 @@ void resize(int aWidth, int aHeight) { mSurfaceTexture.setDefaultBufferSize(aWidth, aHeight); } } + public boolean isLayer() { + return mSurface != null && mSurfaceTexture == null; + } void release() { if(mSurface != null){ diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UIWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UIWidget.java index cd1acb14de..49bec5d87d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UIWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/UIWidget.java @@ -35,6 +35,7 @@ public interface Delegate { } protected UISurfaceTextureRenderer mRenderer; + protected UISurfaceTextureRenderer mProxyRenderer; protected SurfaceTexture mTexture; protected float mWorldWidth; protected int mHandle; @@ -102,6 +103,15 @@ public void setSurfaceTexture(SurfaceTexture aTexture, final int aWidth, final i Log.d(LOGTAG, "Texture already set"); return; } + if (mRenderer != null && mRenderer.isLayer()) { + // Widget is using a layer write-only surface but we also want a proxy. + if (mProxyRenderer != null) { + mProxyRenderer.release(); + } + mProxyRenderer = new UISurfaceTextureRenderer(aTexture, aWidth, aHeight); + postInvalidate(); + return; + } mTexture = aTexture; if (mRenderer != null) { mRenderer.release(); @@ -211,7 +221,19 @@ public void draw(Canvas aCanvas) { super.draw(aCanvas); return; } - Canvas textureCanvas = mRenderer.drawBegin(); + draw(aCanvas, mRenderer); + if (mProxyRenderer != null && mWidgetPlacement.proxifyLayer) { + draw(aCanvas, mProxyRenderer); + } + + if (mFirstDrawCallback != null) { + mFirstDrawCallback.run(); + mFirstDrawCallback = null; + } + } + + private void draw(Canvas aCanvas, UISurfaceTextureRenderer aRenderer) { + Canvas textureCanvas = aRenderer.drawBegin(); if(textureCanvas != null) { // set the proper scale float xScale = textureCanvas.getWidth() / (float)aCanvas.getWidth(); @@ -219,11 +241,7 @@ public void draw(Canvas aCanvas) { // draw the view to SurfaceTexture super.draw(textureCanvas); } - mRenderer.drawEnd(); - if (mFirstDrawCallback != null) { - mFirstDrawCallback.run(); - mFirstDrawCallback = null; - } + aRenderer.drawEnd(); } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetPlacement.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetPlacement.java index 666b478d9d..221c6a86fc 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetPlacement.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WidgetPlacement.java @@ -46,6 +46,7 @@ public WidgetPlacement(Context aContext) { public boolean showPointer = true; public boolean firstDraw = false; public boolean layer = true; + public boolean proxifyLayer = false; public float textureScale = 0.7f; // Widget will be curved if enabled. public boolean cylinder = true; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index 0b9b306aad..74235df662 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -98,7 +98,8 @@ public class WindowWidget extends UIWidget implements SessionChangeListener, boolean mClickedAfterFocus = false; public interface WindowDelegate { - void onFocusRequest(WindowWidget aWindow); + void onFocusRequest(@NonNull WindowWidget aWindow); + void onBorderChanged(@NonNull WindowWidget aWindow); } public WindowWidget(Context aContext, int windowId, boolean privateMode) { @@ -573,6 +574,9 @@ protected void updateBorder() { if (mWidgetPlacement.borderColor != color) { mWidgetPlacement.borderColor = color; mWidgetManager.updateWidget(this); + if (mWindowDelegate != null) { + mWindowDelegate.onBorderChanged(this); + } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java index 8631ed5e2b..e91f90654a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java @@ -25,7 +25,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; -public class Windows implements TrayListener, TopBarWidget.Delegate, GeckoSession.ContentDelegate { +public class Windows implements TrayListener, TopBarWidget.Delegate, GeckoSession.ContentDelegate, WindowWidget.WindowDelegate { private static final String LOGTAG = Windows.class.getSimpleName(); @@ -86,6 +86,7 @@ public enum WindowPlacement{ public interface Delegate { void onFocusedWindowChanged(@NonNull WindowWidget aFocusedWindow, @Nullable WindowWidget aPrevFocusedWindow); + void onWindowBorderChanged(@NonNull WindowWidget aChangeWindow); } public Windows(Context aContext) { @@ -347,6 +348,7 @@ public void onPause() { } public void onDestroy() { + mDelegate = null; for (WindowWidget window: mRegularWindows) { window.close(); } @@ -436,7 +438,7 @@ private void showMaxWindowsMessage() { mFocusedWindow.showMaxWindowsDialog(MAX_WINDOWS); } - private ArrayList getCurrentWindows() { + public ArrayList getCurrentWindows() { return mPrivateMode ? mPrivateWindows : mRegularWindows; } @@ -665,7 +667,7 @@ private void updateTopBars() { private WindowWidget createWindow() { int newWindowId = sIndex++; WindowWidget window = new WindowWidget(mContext, newWindowId, mPrivateMode); - window.setWindowDelegate(this::focusWindow); + window.setWindowDelegate(this); getCurrentWindows().add(window); window.getTopBar().setDelegate(this); window.getSessionStack().addContentListener(this); @@ -784,4 +786,18 @@ private WindowWidget getWindowWithSession(GeckoSession aSession) { return null; } + // WindowWidget.Delegate + @Override + public void onFocusRequest(WindowWidget aWindow) { + focusWindow(aWindow); + } + + @Override + public void onBorderChanged(WindowWidget aWindow) { + if (mDelegate != null) { + mDelegate.onWindowBorderChanged(aWindow); + } + + } + } diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp index a5699ea681..8ea32cd799 100644 --- a/app/src/main/cpp/BrowserWorld.cpp +++ b/app/src/main/cpp/BrowserWorld.cpp @@ -911,6 +911,7 @@ BrowserWorld::UpdateWidget(int32_t aHandle, const WidgetPlacementPtr& aPlacement } widget->SetBorderColor(vrb::Color(aPlacement->borderColor)); + widget->SetProxifyLayer(aPlacement->proxifyLayer); LayoutWidget(aHandle); } diff --git a/app/src/main/cpp/Cylinder.cpp b/app/src/main/cpp/Cylinder.cpp index 2a7b810778..134750f8db 100644 --- a/app/src/main/cpp/Cylinder.cpp +++ b/app/src/main/cpp/Cylinder.cpp @@ -217,6 +217,18 @@ Cylinder::Create(vrb::CreationContextPtr aContext, const float aRadius, const fl return result; } +CylinderPtr +Cylinder::Create(vrb::CreationContextPtr aContext, const Cylinder& aCylinder) { + CylinderPtr result = std::make_shared >(aContext); + result->m.radius = aCylinder.m.radius; + result->m.height = aCylinder.m.height; + result->m.solidColor = aCylinder.m.solidColor; + result->m.border = aCylinder.m.border;; + result->m.borderColor = aCylinder.m.borderColor; + result->m.Initialize(); + return result; +} + CylinderPtr Cylinder::Create(vrb::CreationContextPtr aContext, const VRLayerCylinderPtr& aLayer) { CylinderPtr result = std::make_shared >(aContext); diff --git a/app/src/main/cpp/Cylinder.h b/app/src/main/cpp/Cylinder.h index d378a4108c..d390c02289 100644 --- a/app/src/main/cpp/Cylinder.h +++ b/app/src/main/cpp/Cylinder.h @@ -29,6 +29,7 @@ class Cylinder { static CylinderPtr Create(vrb::CreationContextPtr aContext, const float aRadius, const float aHeight, const VRLayerCylinderPtr& aLayer = nullptr); static CylinderPtr Create(vrb::CreationContextPtr aContext, const float aRadius, const float aHeight, const vrb::Color& aSolidColor, const float kBorder, const vrb::Color& aBorderColor); static CylinderPtr Create(vrb::CreationContextPtr aContext, const VRLayerCylinderPtr& aLayer = nullptr); + static CylinderPtr Create(vrb::CreationContextPtr aContext, const Cylinder& aCylinder); static float kWorldDensityRatio; void GetTextureSize(int32_t& aWidth, int32_t& aHeight) const; void SetTextureSize(int32_t aWidth, int32_t aHeight); diff --git a/app/src/main/cpp/Quad.cpp b/app/src/main/cpp/Quad.cpp index 896c23037d..a6eb09e6be 100644 --- a/app/src/main/cpp/Quad.cpp +++ b/app/src/main/cpp/Quad.cpp @@ -166,6 +166,15 @@ Quad::Create(vrb::CreationContextPtr aContext, const float aWorldWidth, const fl return result; } +QuadPtr +Quad::Create(vrb::CreationContextPtr aContext, const Quad& aQuad) { + QuadPtr result = std::make_shared >(aContext); + result->m.worldMin = aQuad.m.worldMin; + result->m.worldMax = aQuad.m.worldMax; + result->m.Initialize(); + return result; +} + vrb::GeometryPtr Quad::CreateGeometry(vrb::CreationContextPtr aContext, const vrb::Vector &aMin, const vrb::Vector &aMax) { device::EyeRect rect(0.0f, 0.0f, 1.0f, 1.0f); diff --git a/app/src/main/cpp/Quad.h b/app/src/main/cpp/Quad.h index 56c158dbcf..a8cebf5b10 100644 --- a/app/src/main/cpp/Quad.h +++ b/app/src/main/cpp/Quad.h @@ -33,6 +33,7 @@ class Quad { }; static QuadPtr Create(vrb::CreationContextPtr aContext, const vrb::Vector& aMin, const vrb::Vector& aMax, const VRLayerQuadPtr& aLayer = nullptr); static QuadPtr Create(vrb::CreationContextPtr aContext, const float aWorldWidth, const float aWorldHeight, const VRLayerQuadPtr& aLayer = nullptr); + static QuadPtr Create(vrb::CreationContextPtr aContext, const Quad& aQuad); static vrb::GeometryPtr CreateGeometry(vrb::CreationContextPtr aContext, const vrb::Vector& aMin, const vrb::Vector& aMax); static vrb::GeometryPtr CreateGeometry(vrb::CreationContextPtr aContext, const float aWorldWidth, const float aWorldHeight); static vrb::GeometryPtr CreateGeometry(vrb::CreationContextPtr aContext, const vrb::Vector& aMin, const vrb::Vector& aMax, const device::EyeRect& aRect); diff --git a/app/src/main/cpp/Widget.cpp b/app/src/main/cpp/Widget.cpp index d84d5b8012..41ff8ac2d6 100644 --- a/app/src/main/cpp/Widget.cpp +++ b/app/src/main/cpp/Widget.cpp @@ -15,7 +15,10 @@ #include "vrb/Color.h" #include "vrb/RenderContext.h" +#include "vrb/CreationContext.h" +#include "vrb/TextureGL.h" #include "vrb/Matrix.h" +#include "vrb/GLError.h" #include "vrb/Geometry.h" #include "vrb/RenderState.h" #include "vrb/SurfaceTextureFactory.h" @@ -54,6 +57,7 @@ struct Widget::State { bool toggleState; vrb::TogglePtr bordersContainer; std::vector borders; + vrb::TogglePtr layerProxy; State() : handle(0) @@ -544,6 +548,49 @@ Widget::SetBorderColor(const vrb::Color &aColor) { } } +void +Widget::SetProxifyLayer(const bool aValue) { + if (!aValue) { + if (m.layerProxy) { + m.layerProxy->ToggleAll(false); + } + return; + } + + if (!m.layerProxy) { + vrb::RenderContextPtr render = m.context.lock(); + vrb::CreationContextPtr create = render->GetRenderThreadCreationContext(); + m.layerProxy = vrb::Toggle::Create(create); + // Proxy objects must clear the existing surface, so set a proper blend function. + m.layerProxy->SetPreRenderLambda([]() { + VRB_GL_CHECK(glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA)); + }); + m.layerProxy->SetPostRenderLambda([]() { + VRB_GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + }); + m.transform->AddNode(m.layerProxy); + int32_t textureWidth, textureHeight; + GetSurfaceTextureSize(textureWidth, textureHeight); + // Reduce quality, proxy objects do not need full quality. + textureWidth /= 2; + textureHeight /= 2; + vrb::TextureSurfacePtr proxySurface = vrb::TextureSurface::Create(render, m.name); + if (m.cylinder) { + CylinderPtr proxy = Cylinder::Create(create, *m.cylinder); + proxy->SetCylinderTheta(m.cylinder->GetCylinderTheta()); + proxy->SetTexture(proxySurface, textureWidth, textureHeight); + proxy->SetTransform(m.cylinder->GetTransformNode()->GetTransform()); + m.layerProxy->AddNode(proxy->GetRoot()); + } else { + QuadPtr proxy = Quad::Create(create, *m.quad); + proxy->SetTexture(proxySurface, textureWidth, textureHeight); + m.layerProxy->AddNode(proxy->GetRoot()); + } + } + + m.layerProxy->ToggleAll(true); +} + Widget::Widget(State& aState, vrb::RenderContextPtr& aContext) : m(aState) { m.context = aContext; } diff --git a/app/src/main/cpp/Widget.h b/app/src/main/cpp/Widget.h index f8e04d113e..bc6d5b8d7d 100644 --- a/app/src/main/cpp/Widget.h +++ b/app/src/main/cpp/Widget.h @@ -75,6 +75,7 @@ class Widget { void SetCylinderDensity(const float aDensity); float GetCylinderDensity() const; void SetBorderColor(const vrb::Color& aColor); + void SetProxifyLayer(const bool aValue); protected: struct State; Widget(State& aState, vrb::RenderContextPtr& aContext); diff --git a/app/src/main/cpp/WidgetPlacement.cpp b/app/src/main/cpp/WidgetPlacement.cpp index 14fdd1b51b..5556f16808 100644 --- a/app/src/main/cpp/WidgetPlacement.cpp +++ b/app/src/main/cpp/WidgetPlacement.cpp @@ -55,6 +55,7 @@ WidgetPlacement::FromJava(JNIEnv* aEnv, jobject& aObject) { GET_BOOLEAN_FIELD(showPointer); GET_BOOLEAN_FIELD(firstDraw); GET_BOOLEAN_FIELD(layer); + GET_BOOLEAN_FIELD(proxifyLayer); GET_FLOAT_FIELD(textureScale, "textureScale"); GET_BOOLEAN_FIELD(cylinder); GET_FLOAT_FIELD(cylinderMapRadius, "cylinderMapRadius"); diff --git a/app/src/main/cpp/WidgetPlacement.h b/app/src/main/cpp/WidgetPlacement.h index 3493fbbdcf..4cc4d23c64 100644 --- a/app/src/main/cpp/WidgetPlacement.h +++ b/app/src/main/cpp/WidgetPlacement.h @@ -31,6 +31,7 @@ struct WidgetPlacement { bool showPointer; bool firstDraw; bool layer; + bool proxifyLayer; float textureScale; bool cylinder; float cylinderMapRadius; diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 9a7a2539a0..74057b58a9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -38,6 +38,6 @@ #8F000000 #7FFFFFFF #f5f6fa - #FF2BD5D5 - #FF1AC4C4 + #1ac1dd + #2bd2ee