From 5e216bb16e11999d90ef184092d0495b1cfdce22 Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Fri, 17 May 2019 13:33:49 +0200 Subject: [PATCH] Block background UI interaction for dialogs (#1211) --- .../mozilla/vrbrowser/VRBrowserActivity.java | 31 +++++++++++- .../vrbrowser/ui/widgets/UIWidget.java | 5 ++ .../mozilla/vrbrowser/ui/widgets/Widget.java | 1 + .../ui/widgets/dialogs/CrashDialogWidget.java | 10 +--- .../ui/widgets/dialogs/PermissionWidget.java | 20 +------- .../widgets/dialogs/RestartDialogWidget.java | 2 +- .../ui/widgets/dialogs/UIDialog.java | 48 +++++++++++++++++++ .../ui/widgets/dialogs/VoiceSearchWidget.java | 15 +----- .../ui/widgets/prompts/AlertPromptWidget.java | 3 -- .../ui/widgets/prompts/AuthPromptWidget.java | 3 -- .../widgets/prompts/ChoicePromptWidget.java | 3 -- .../widgets/prompts/ConfirmPromptWidget.java | 3 -- .../ui/widgets/prompts/PromptWidget.java | 13 +---- .../ui/widgets/prompts/TextPromptWidget.java | 3 -- .../ui/widgets/settings/SettingsWidget.java | 5 +- 15 files changed, 92 insertions(+), 73 deletions(-) create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 312c22717..68a44179c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -141,6 +141,7 @@ public void run() { private ConnectivityReceiver mConnectivityReceiver; private boolean mConnectionAvailable = true; private AudioManager mAudioManager; + private Widget mActiveDialog; private boolean callOnAudioManager(Consumer fn) { if (mAudioManager == null) { @@ -588,6 +589,9 @@ void dispatchCreateWidgetLayer(final int aHandle, final Surface aSurface, final void handleMotionEvent(final int aHandle, final int aDevice, final boolean aPressed, final float aX, final float aY) { runOnUiThread(() -> { Widget widget = mWidgets.get(aHandle); + if (!isWidgetInputEnabled(widget)) { + widget = null; // Fallback to mRootWidget in order to allow world clicks to dismiss UI. + } float scale = widget != null ? widget.getPlacement().textureScale : 1.0f; final float x = aX / scale; final float y = aY / scale; @@ -608,6 +612,9 @@ void handleMotionEvent(final int aHandle, final int aDevice, final boolean aPres void handleScrollEvent(final int aHandle, final int aDevice, final float aX, final float aY) { runOnUiThread(() -> { Widget widget = mWidgets.get(aHandle); + if (!isWidgetInputEnabled(widget)) { + return; + } if (widget != null) { float scrollDirection = mSettings.getScrollDirection() == 0 ? 1.0f : -1.0f; MotionEventGenerator.dispatchScroll(widget, aDevice, aX * scrollDirection, aY * scrollDirection); @@ -842,6 +849,22 @@ public void addWidgets(final Iterable aWidgets) { }); } + private void updateActiveDialog(final Widget aWidget) { + if (!aWidget.isDialog()) { + return; + } + + if (aWidget.isVisible()) { + mActiveDialog = aWidget; + } else if (aWidget == mActiveDialog && !aWidget.isVisible()) { + mActiveDialog = null; + } + } + + private boolean isWidgetInputEnabled(Widget aWidget) { + return mActiveDialog == null || aWidget == null || mActiveDialog == aWidget || aWidget instanceof KeyboardWidget; + } + // VideoAvailabilityListener @Override public void onVideoAvailabilityChanged(boolean aVideosAvailable) { @@ -850,10 +873,11 @@ public void onVideoAvailabilityChanged(boolean aVideosAvailable) { // WidgetManagerDelegate @Override - public void addWidget(final Widget aWidget) { + public void addWidget(Widget aWidget) { mWidgets.put(aWidget.getHandle(), aWidget); ((View)aWidget).setVisibility(aWidget.getPlacement().visible ? View.VISIBLE : View.GONE); queueRunnable(() -> addWidgetNative(aWidget.getHandle(), aWidget.getPlacement())); + updateActiveDialog(aWidget); } @Override @@ -886,7 +910,7 @@ public void updateWidget(final Widget aWidget) { for (UpdateListener listener: mWidgetUpdateListeners) { listener.onWidgetUpdate(aWidget); } - + updateActiveDialog(aWidget); } @Override @@ -895,6 +919,9 @@ public void removeWidget(final Widget aWidget) { mWidgetContainer.removeView((View) aWidget); aWidget.setFirstDraw(false); queueRunnable(() -> removeWidgetNative(aWidget.getHandle())); + if (aWidget == mActiveDialog) { + mActiveDialog = null; + } } @Override 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 b6516ca73..d78cb3dac 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 @@ -182,6 +182,11 @@ public void releaseWidget() { mWidgetManager = null; } + @Override + public boolean isDialog() { + return false; + } + @Override public void setFirstDraw(final boolean aIsFirstDraw) { mWidgetPlacement.firstDraw = aIsFirstDraw; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Widget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Widget.java index a8fc78e78..640d9f7ca 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Widget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Widget.java @@ -24,6 +24,7 @@ public interface Widget { void setFirstDraw(boolean aIsFirstDraw); boolean getFirstDraw(); boolean isVisible(); + boolean isDialog(); void setVisible(boolean aVisible); void resizeByMultiplier(float aspect, float multiplier); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java index 64a605bdf..e221d3c17 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java @@ -21,7 +21,7 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; -public class CrashDialogWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { +public class CrashDialogWidget extends UIDialog { private static final String LOGTAG = "VRB"; @@ -150,12 +150,4 @@ public void hide(@HideFlags int aHideFlags) { public void setCrashDialogDelegate(CrashDialogDelegate aDelegate) { mCrashDialogDelegate = aDelegate; } - - // WidgetManagerDelegate.FocusChangeListener - @Override - public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (oldFocus == this && isVisible()) { - onDismiss(); - } - } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java index 6cc075d07..415f3d0fc 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java @@ -23,7 +23,7 @@ import java.net.URI; -public class PermissionWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { +public class PermissionWidget extends UIDialog implements WidgetManagerDelegate.FocusChangeListener { private static final String LOGTAG = "VRB"; @@ -58,8 +58,6 @@ public PermissionWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { private void initialize(Context aContext) { inflate(aContext, R.layout.permission, this); - mWidgetManager.addFocusChangeListener(this); - mPermissionIcon = findViewById(R.id.permissionIcon); mPermissionMessage = findViewById(R.id.permissionText); @@ -70,13 +68,6 @@ private void initialize(Context aContext) { allowButton.setOnClickListener(v -> handlePermissionResult(true)); } - @Override - public void releaseWidget() { - mWidgetManager.removeFocusChangeListener(this); - - super.releaseWidget(); - } - @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { Context context = getContext(); @@ -177,13 +168,4 @@ private void handlePermissionResult(boolean aGranted) { onDismiss(); } - - // WidgetManagerDelegate.FocusChangeListener - - @Override - public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (oldFocus == this && isVisible()) { - onDismiss(); - } - } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java index d9bb9ca3d..f655dfaf4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java @@ -19,7 +19,7 @@ import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; -public class RestartDialogWidget extends UIWidget { +public class RestartDialogWidget extends UIDialog { private static final String LOGTAG = "VRB"; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java new file mode 100644 index 000000000..b9df4a081 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java @@ -0,0 +1,48 @@ +package org.mozilla.vrbrowser.ui.widgets.dialogs; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import org.mozilla.vrbrowser.ui.widgets.UIWidget; +import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; + +public abstract class UIDialog extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { + public UIDialog(Context aContext) { + super(aContext); + initialize(); + } + + public UIDialog(Context aContext, AttributeSet aAttrs) { + super(aContext, aAttrs); + initialize(); + } + + public UIDialog(Context aContext, AttributeSet aAttrs, int aDefStyle) { + super(aContext, aAttrs, aDefStyle); + initialize(); + } + + private void initialize() { + mWidgetManager.addFocusChangeListener(this); + } + + @Override + public void releaseWidget() { + super.releaseWidget(); + mWidgetManager.removeFocusChangeListener(this); + } + + @Override + public boolean isDialog() { + return true; + } + + // WidgetManagerDelegate.FocusChangeListener + @Override + public void onGlobalFocusChanged(View oldFocus, View newFocus) { + if (oldFocus == this && isVisible()) { + onDismiss(); + } + } +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java index 852e79e13..7a16126c5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java @@ -35,8 +35,8 @@ import androidx.annotation.IdRes; import androidx.core.app.ActivityCompat; -public class VoiceSearchWidget extends UIWidget implements WidgetManagerDelegate.PermissionListener, - Application.ActivityLifecycleCallbacks, WidgetManagerDelegate.FocusChangeListener { +public class VoiceSearchWidget extends UIDialog implements WidgetManagerDelegate.PermissionListener, + Application.ActivityLifecycleCallbacks { private static final String LOGTAG = "VRB"; private static final int VOICESEARCH_AUDIO_REQUEST_CODE = 7455; @@ -87,7 +87,6 @@ private void initialize(Context aContext) { mAudio = AudioEngine.fromContext(aContext); - mWidgetManager.addFocusChangeListener(this); mWidgetManager.addPermissionListener(this); mMozillaSpeechService = MozillaSpeechService.getInstance(); @@ -135,7 +134,6 @@ public void setDelegate(VoiceSearchDelegate delegate) { @Override public void releaseWidget() { - mWidgetManager.removeFocusChangeListener(this); mWidgetManager.removePermissionListener(this); mMozillaSpeechService.removeListener(mVoiceSearchListener); ((Application)getContext().getApplicationContext()).unregisterActivityLifecycleCallbacks(this); @@ -370,13 +368,4 @@ public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { public void onActivityDestroyed(Activity activity) { } - - // WidgetManagerDelegate.FocusChangeListener - @Override - public void onGlobalFocusChanged(View oldFocus, View newFocus) { - if (isVisible()) { - hide(REMOVE_WIDGET); - } - } - } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AlertPromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AlertPromptWidget.java index 497d08353..3e6377f29 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AlertPromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AlertPromptWidget.java @@ -30,10 +30,7 @@ public AlertPromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { initialize(aContext); } - @Override protected void initialize(Context aContext) { - super.initialize(aContext); - inflate(aContext, R.layout.prompt_alert, this); mAudio = AudioEngine.fromContext(aContext); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AuthPromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AuthPromptWidget.java index 75a3ab18a..f3c2bfb02 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AuthPromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/AuthPromptWidget.java @@ -42,10 +42,7 @@ public AuthPromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { initialize(aContext); } - @Override protected void initialize(Context aContext) { - super.initialize(aContext); - inflate(aContext, R.layout.prompt_auth, this); mAudio = AudioEngine.fromContext(aContext); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ChoicePromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ChoicePromptWidget.java index ac77b6a70..062dcc088 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ChoicePromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ChoicePromptWidget.java @@ -57,10 +57,7 @@ public ChoicePromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) initialize(aContext); } - @Override protected void initialize(Context aContext) { - super.initialize(aContext); - inflate(aContext, R.layout.prompt_choice, this); mWidgetManager.addFocusChangeListener(this); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ConfirmPromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ConfirmPromptWidget.java index 1e03bb65d..4f7df8c99 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ConfirmPromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/ConfirmPromptWidget.java @@ -35,10 +35,7 @@ public ConfirmPromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) initialize(aContext); } - @Override protected void initialize(Context aContext) { - super.initialize(aContext); - inflate(aContext, R.layout.prompt_confirm, this); mWidgetManager.addFocusChangeListener(this); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java index 79b2a6f84..b468a0067 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java @@ -11,8 +11,9 @@ import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; +import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; -public class PromptWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { +public class PromptWidget extends UIDialog { protected TextView mTitle; protected TextView mMessage; @@ -31,10 +32,6 @@ public PromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { super(aContext, aAttrs, aDefStyle); } - protected void initialize(Context aContext) { - mWidgetManager.addFocusChangeListener(this); - } - public void setTitle(String title) { if (title == null || title.isEmpty()) { mTitle.setVisibility(View.GONE); @@ -66,12 +63,6 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.browser_children_z_distance); } - @Override - public void releaseWidget() { - mWidgetManager.removeFocusChangeListener(this); - - super.releaseWidget(); - } @Override public void show() { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/TextPromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/TextPromptWidget.java index db61e451b..8324d99ea 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/TextPromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/TextPromptWidget.java @@ -33,10 +33,7 @@ public TextPromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { initialize(aContext); } - @Override protected void initialize(Context aContext) { - super.initialize(aContext); - inflate(aContext, R.layout.prompt_text, this); mAudio = AudioEngine.fromContext(aContext); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index 45da8524f..946e1107d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -31,6 +31,7 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.ui.widgets.dialogs.RestartDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget; import java.io.UnsupportedEncodingException; @@ -39,7 +40,7 @@ import java.util.Calendar; import java.util.GregorianCalendar; -public class SettingsWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener, WidgetManagerDelegate.WorldClickListener, SettingsView.Delegate { +public class SettingsWidget extends UIDialog implements WidgetManagerDelegate.WorldClickListener, SettingsView.Delegate { private static final String LOGTAG = "VRB"; private AudioEngine mAudio; private SettingsView mCurrentView; @@ -82,7 +83,6 @@ public SettingsWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { private void initialize(Context aContext) { inflate(aContext, R.layout.settings, this); - mWidgetManager.addFocusChangeListener(this); mWidgetManager.addWorldClickListener(this); mMainLayout = findViewById(R.id.optionsLayout); @@ -211,7 +211,6 @@ private void initialize(Context aContext) { @Override public void releaseWidget() { mWidgetManager.removeWorldClickListener(this); - mWidgetManager.removeFocusChangeListener(this); super.releaseWidget(); }