From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../org/mozilla/gecko/GeckoScreenOrientation.java | 273 +++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java') diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java new file mode 100644 index 0000000000..bdb7b4b331 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java @@ -0,0 +1,273 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; + +import android.content.Context; +import android.graphics.Rect; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import java.util.ArrayList; +import java.util.List; +import org.mozilla.gecko.util.ThreadUtils; + +/* + * Updates, locks and unlocks the screen orientation. + * + * Note: Replaces the OnOrientationChangeListener to avoid redundant rotation + * event handling. + */ +public class GeckoScreenOrientation { + private static final String LOGTAG = "GeckoScreenOrientation"; + + // Make sure that any change in hal/HalScreenConfiguration.h happens here too. + public enum ScreenOrientation { + NONE(0), + PORTRAIT_PRIMARY(1 << 0), + PORTRAIT_SECONDARY(1 << 1), + PORTRAIT(PORTRAIT_PRIMARY.value | PORTRAIT_SECONDARY.value), + LANDSCAPE_PRIMARY(1 << 2), + LANDSCAPE_SECONDARY(1 << 3), + LANDSCAPE(LANDSCAPE_PRIMARY.value | LANDSCAPE_SECONDARY.value), + ANY( + PORTRAIT_PRIMARY.value + | PORTRAIT_SECONDARY.value + | LANDSCAPE_PRIMARY.value + | LANDSCAPE_SECONDARY.value), + DEFAULT(1 << 4); + + public final short value; + + private ScreenOrientation(final int value) { + this.value = (short) value; + } + + private static final ScreenOrientation[] sValues = ScreenOrientation.values(); + + public static ScreenOrientation get(final int value) { + for (final ScreenOrientation orient : sValues) { + if (orient.value == value) { + return orient; + } + } + return NONE; + } + } + + // Singleton instance. + private static GeckoScreenOrientation sInstance; + // Default rotation, used when device rotation is unknown. + private static final int DEFAULT_ROTATION = Surface.ROTATION_0; + // Last updated screen orientation with Gecko value space. + private ScreenOrientation mScreenOrientation = ScreenOrientation.PORTRAIT_PRIMARY; + + public interface OrientationChangeListener { + void onScreenOrientationChanged(ScreenOrientation newOrientation); + } + + private final List mListeners; + + public static GeckoScreenOrientation getInstance() { + if (sInstance == null) { + sInstance = new GeckoScreenOrientation(); + } + return sInstance; + } + + private GeckoScreenOrientation() { + mListeners = new ArrayList<>(); + update(); + } + + /** Add a listener that will be notified when the screen orientation has changed. */ + public void addListener(final OrientationChangeListener aListener) { + ThreadUtils.assertOnUiThread(); + mListeners.add(aListener); + } + + /** Remove a OrientationChangeListener again. */ + public void removeListener(final OrientationChangeListener aListener) { + ThreadUtils.assertOnUiThread(); + mListeners.remove(aListener); + } + + /* + * Update screen orientation. + * Retrieve orientation and rotation via GeckoAppShell. + * + * @return Whether the screen orientation has changed. + */ + public boolean update() { + // Check whether we have the application context for fenix/a-c unit test. + final Context appContext = GeckoAppShell.getApplicationContext(); + if (appContext == null) { + return false; + } + final Rect rect = GeckoAppShell.getScreenSizeIgnoreOverride(); + final int orientation = + rect.width() >= rect.height() ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; + return update(getScreenOrientation(orientation, getRotation())); + } + + /* + * Update screen orientation. + * Retrieve orientation and rotation via Display. + * + * @param aDisplay The Display that has screen orientation information + * + * @return Whether the screen orientation has changed. + */ + public boolean update(final Display aDisplay) { + return update(getScreenOrientation(aDisplay)); + } + + /* + * Update screen orientation given the android orientation. + * Retrieve rotation via GeckoAppShell. + * + * @param aAndroidOrientation + * Android screen orientation from Configuration.orientation. + * + * @return Whether the screen orientation has changed. + */ + public boolean update(final int aAndroidOrientation) { + return update(getScreenOrientation(aAndroidOrientation, getRotation())); + } + + /* + * Update screen orientation given the screen orientation. + * + * @param aScreenOrientation + * Gecko screen orientation based on android orientation and rotation. + * + * @return Whether the screen orientation has changed. + */ + public synchronized boolean update(final ScreenOrientation aScreenOrientation) { + // Gecko expects a definite screen orientation, so we default to the + // primary orientations. + final ScreenOrientation screenOrientation; + if ((aScreenOrientation.value & ScreenOrientation.PORTRAIT_PRIMARY.value) != 0) { + screenOrientation = ScreenOrientation.PORTRAIT_PRIMARY; + } else if ((aScreenOrientation.value & ScreenOrientation.PORTRAIT_SECONDARY.value) != 0) { + screenOrientation = ScreenOrientation.PORTRAIT_SECONDARY; + } else if ((aScreenOrientation.value & ScreenOrientation.LANDSCAPE_PRIMARY.value) != 0) { + screenOrientation = ScreenOrientation.LANDSCAPE_PRIMARY; + } else if ((aScreenOrientation.value & ScreenOrientation.LANDSCAPE_SECONDARY.value) != 0) { + screenOrientation = ScreenOrientation.LANDSCAPE_SECONDARY; + } else { + screenOrientation = ScreenOrientation.PORTRAIT_PRIMARY; + } + if (mScreenOrientation == screenOrientation) { + return false; + } + mScreenOrientation = screenOrientation; + Log.d(LOGTAG, "updating to new orientation " + mScreenOrientation); + notifyListeners(mScreenOrientation); + ScreenManagerHelper.refreshScreenInfo(); + return true; + } + + private void notifyListeners(final ScreenOrientation newOrientation) { + final Runnable notifier = + new Runnable() { + @Override + public void run() { + for (final OrientationChangeListener listener : mListeners) { + listener.onScreenOrientationChanged(newOrientation); + } + } + }; + + if (ThreadUtils.isOnUiThread()) { + notifier.run(); + } else { + ThreadUtils.runOnUiThread(notifier); + } + } + + /* + * @return The Gecko screen orientation derived from Android orientation and + * rotation. + */ + public ScreenOrientation getScreenOrientation() { + return mScreenOrientation; + } + + /* + * Combine the Android orientation and rotation to the Gecko orientation. + * + * @param aAndroidOrientation + * Android orientation from Configuration.orientation. + * @param aRotation + * Device rotation from Display.getRotation(). + * + * @return Gecko screen orientation. + */ + private ScreenOrientation getScreenOrientation( + final int aAndroidOrientation, final int aRotation) { + final boolean isPrimary = aRotation == Surface.ROTATION_0 || aRotation == Surface.ROTATION_90; + if (aAndroidOrientation == ORIENTATION_PORTRAIT) { + if (isPrimary) { + // Non-rotated portrait device or landscape device rotated + // to primary portrait mode counter-clockwise. + return ScreenOrientation.PORTRAIT_PRIMARY; + } + return ScreenOrientation.PORTRAIT_SECONDARY; + } + if (aAndroidOrientation == ORIENTATION_LANDSCAPE) { + if (isPrimary) { + // Non-rotated landscape device or portrait device rotated + // to primary landscape mode counter-clockwise. + return ScreenOrientation.LANDSCAPE_PRIMARY; + } + return ScreenOrientation.LANDSCAPE_SECONDARY; + } + return ScreenOrientation.NONE; + } + + /* + * Get the Gecko orientation from Display. + * + * @param aDisplay The display that has orientation information. + * + * @return Gecko screen orientation. + */ + private ScreenOrientation getScreenOrientation(final Display aDisplay) { + final Rect rect = GeckoAppShell.getScreenSizeIgnoreOverride(); + final int orientation = + rect.width() >= rect.height() ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; + return getScreenOrientation(orientation, aDisplay.getRotation()); + } + + /* + * @return Device rotation converted to an angle. + */ + public short getAngle() { + switch (getRotation()) { + case Surface.ROTATION_0: + return 0; + case Surface.ROTATION_90: + return 90; + case Surface.ROTATION_180: + return 180; + case Surface.ROTATION_270: + return 270; + default: + Log.w(LOGTAG, "getAngle: unexpected rotation value"); + return 0; + } + } + + /* + * @return Device rotation. + */ + private int getRotation() { + return GeckoAppShell.getRotation(); + } +} -- cgit v1.2.3