2014-02-20 09:50:18 -08:00
|
|
|
/* -*- 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 android.content.pm.ActivityInfo;
|
|
|
|
import android.content.res.Configuration;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.Surface;
|
|
|
|
import android.app.Activity;
|
|
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 dom/base/ScreenOrientation.h happens here too.
|
|
|
|
public enum ScreenOrientation {
|
|
|
|
NONE(0),
|
|
|
|
PORTRAIT_PRIMARY(1 << 0),
|
|
|
|
PORTRAIT_SECONDARY(1 << 1),
|
|
|
|
LANDSCAPE_PRIMARY(1 << 2),
|
|
|
|
LANDSCAPE_SECONDARY(1 << 3),
|
|
|
|
DEFAULT(1 << 4);
|
|
|
|
|
|
|
|
public final short value;
|
|
|
|
|
|
|
|
private ScreenOrientation(int value) {
|
|
|
|
this.value = (short)value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static ScreenOrientation get(short value) {
|
|
|
|
switch (value) {
|
|
|
|
case (1 << 0): return PORTRAIT_PRIMARY;
|
|
|
|
case (1 << 1): return PORTRAIT_SECONDARY;
|
|
|
|
case (1 << 2): return LANDSCAPE_PRIMARY;
|
|
|
|
case (1 << 3): return LANDSCAPE_SECONDARY;
|
|
|
|
case (1 << 4): return DEFAULT;
|
|
|
|
default: return NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Singleton instance.
|
2014-07-25 20:14:47 -07:00
|
|
|
private static GeckoScreenOrientation sInstance;
|
2014-02-20 09:50:18 -08:00
|
|
|
// Default screen orientation, used for initialization and unlocking.
|
|
|
|
private static final ScreenOrientation DEFAULT_SCREEN_ORIENTATION = ScreenOrientation.DEFAULT;
|
|
|
|
// Default rotation, used when device rotation is unknown.
|
|
|
|
private static final int DEFAULT_ROTATION = Surface.ROTATION_0;
|
|
|
|
// Default orientation, used if screen orientation is unspecified.
|
|
|
|
private ScreenOrientation mDefaultScreenOrientation;
|
|
|
|
// Last updated screen orientation.
|
|
|
|
private ScreenOrientation mScreenOrientation;
|
|
|
|
// Whether the update should notify Gecko about screen orientation changes.
|
|
|
|
private boolean mShouldNotify = true;
|
|
|
|
// Configuration screen orientation preference path.
|
|
|
|
private static final String DEFAULT_SCREEN_ORIENTATION_PREF = "app.orientation.default";
|
|
|
|
|
|
|
|
public GeckoScreenOrientation() {
|
|
|
|
PrefsHelper.getPref(DEFAULT_SCREEN_ORIENTATION_PREF, new PrefsHelper.PrefHandlerBase() {
|
|
|
|
@Override public void prefValue(String pref, String value) {
|
|
|
|
// Read and update the configuration default preference.
|
|
|
|
mDefaultScreenOrientation = screenOrientationFromArrayString(value);
|
|
|
|
setRequestedOrientation(mDefaultScreenOrientation);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
mDefaultScreenOrientation = DEFAULT_SCREEN_ORIENTATION;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static GeckoScreenOrientation getInstance() {
|
|
|
|
if (sInstance == null) {
|
|
|
|
sInstance = new GeckoScreenOrientation();
|
|
|
|
}
|
|
|
|
return sInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable Gecko screen orientation events on update.
|
|
|
|
*/
|
|
|
|
public void enableNotifications() {
|
|
|
|
update();
|
|
|
|
mShouldNotify = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable Gecko screen orientation events on update.
|
|
|
|
*/
|
|
|
|
public void disableNotifications() {
|
|
|
|
mShouldNotify = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update screen orientation.
|
|
|
|
* Retrieve orientation and rotation via GeckoAppShell.
|
|
|
|
*
|
|
|
|
* @return Whether the screen orientation has changed.
|
|
|
|
*/
|
|
|
|
public boolean update() {
|
|
|
|
Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
|
|
|
|
if (activity == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Configuration config = activity.getResources().getConfiguration();
|
|
|
|
return update(config.orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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(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 boolean update(ScreenOrientation aScreenOrientation) {
|
|
|
|
if (mScreenOrientation == aScreenOrientation) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mScreenOrientation = aScreenOrientation;
|
|
|
|
Log.d(LOGTAG, "updating to new orientation " + mScreenOrientation);
|
|
|
|
if (mShouldNotify) {
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenOrientationEvent(mScreenOrientation.value));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @return The Android orientation (Configuration.orientation).
|
|
|
|
*/
|
|
|
|
public int getAndroidOrientation() {
|
|
|
|
return screenOrientationToAndroidOrientation(getScreenOrientation());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @return The Gecko screen orientation derived from Android orientation and
|
|
|
|
* rotation.
|
|
|
|
*/
|
|
|
|
public ScreenOrientation getScreenOrientation() {
|
|
|
|
return mScreenOrientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock screen orientation given the Android orientation.
|
|
|
|
* Retrieve rotation via GeckoAppShell.
|
|
|
|
*
|
|
|
|
* @param aAndroidOrientation
|
|
|
|
* The Android orientation provided by Configuration.orientation.
|
|
|
|
*/
|
|
|
|
public void lock(int aAndroidOrientation) {
|
|
|
|
lock(getScreenOrientation(aAndroidOrientation, getRotation()));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock screen orientation given the Gecko screen orientation.
|
|
|
|
* Retrieve rotation via GeckoAppShell.
|
|
|
|
*
|
|
|
|
* @param aScreenOrientation
|
|
|
|
* Gecko screen orientation derived from Android orientation and
|
|
|
|
* rotation.
|
|
|
|
*
|
|
|
|
* @return Whether the locking was successful.
|
|
|
|
*/
|
|
|
|
public boolean lock(ScreenOrientation aScreenOrientation) {
|
|
|
|
Log.d(LOGTAG, "locking to " + aScreenOrientation);
|
|
|
|
update(aScreenOrientation);
|
|
|
|
return setRequestedOrientation(aScreenOrientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unlock and update screen orientation.
|
|
|
|
*
|
|
|
|
* @return Whether the unlocking was successful.
|
|
|
|
*/
|
|
|
|
public boolean unlock() {
|
|
|
|
Log.d(LOGTAG, "unlocking");
|
|
|
|
setRequestedOrientation(mDefaultScreenOrientation);
|
|
|
|
return update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the given requested orientation for the current activity.
|
|
|
|
* This is essentially an unlock without an update.
|
|
|
|
*
|
|
|
|
* @param aScreenOrientation
|
|
|
|
* Gecko screen orientation.
|
|
|
|
*
|
|
|
|
* @return Whether the requested orientation was set. This can only fail if
|
|
|
|
* the current activity cannot be retrieved vie GeckoAppShell.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
private boolean setRequestedOrientation(ScreenOrientation aScreenOrientation) {
|
|
|
|
int activityOrientation = screenOrientationToActivityInfoOrientation(aScreenOrientation);
|
|
|
|
Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
|
|
|
|
if (activity == null) {
|
|
|
|
Log.w(LOGTAG, "setRequestOrientation: failed to get activity");
|
|
|
|
}
|
|
|
|
if (activity.getRequestedOrientation() == activityOrientation) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
activity.setRequestedOrientation(activityOrientation);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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(int aAndroidOrientation, int aRotation) {
|
|
|
|
boolean isPrimary = aRotation == Surface.ROTATION_0 || aRotation == Surface.ROTATION_90;
|
|
|
|
if (aAndroidOrientation == Configuration.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 == Configuration.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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @return Device rotation from Display.getRotation().
|
|
|
|
*/
|
|
|
|
private int getRotation() {
|
|
|
|
Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
|
|
|
|
if (activity == null) {
|
|
|
|
Log.w(LOGTAG, "getRotation: failed to get activity");
|
|
|
|
return DEFAULT_ROTATION;
|
|
|
|
}
|
|
|
|
return activity.getWindowManager().getDefaultDisplay().getRotation();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve the screen orientation from an array string.
|
|
|
|
*
|
|
|
|
* @param aArray
|
|
|
|
* String containing comma-delimited strings.
|
|
|
|
*
|
|
|
|
* @return First parsed Gecko screen orientation.
|
|
|
|
*/
|
|
|
|
public static ScreenOrientation screenOrientationFromArrayString(String aArray) {
|
|
|
|
List<String> orientations = Arrays.asList(aArray.split(","));
|
|
|
|
if (orientations.size() == 0) {
|
|
|
|
// If nothing is listed, return default.
|
|
|
|
Log.w(LOGTAG, "screenOrientationFromArrayString: no orientation in string");
|
|
|
|
return DEFAULT_SCREEN_ORIENTATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't support multiple orientations yet. To avoid developer
|
|
|
|
// confusion, just take the first one listed.
|
|
|
|
return screenOrientationFromString(orientations.get(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve the scren orientation from a string.
|
|
|
|
*
|
|
|
|
* @param aStr
|
|
|
|
* String hopefully containing a screen orientation name.
|
|
|
|
* @return Gecko screen orientation if matched, DEFAULT_SCREEN_ORIENTATION
|
|
|
|
* otherwise.
|
|
|
|
*/
|
|
|
|
public static ScreenOrientation screenOrientationFromString(String aStr) {
|
|
|
|
if ("portrait".equals(aStr)) {
|
|
|
|
return ScreenOrientation.PORTRAIT_PRIMARY;
|
|
|
|
}
|
|
|
|
else if ("landscape".equals(aStr)) {
|
|
|
|
return ScreenOrientation.LANDSCAPE_PRIMARY;
|
|
|
|
}
|
|
|
|
else if ("portrait-primary".equals(aStr)) {
|
|
|
|
return ScreenOrientation.PORTRAIT_PRIMARY;
|
|
|
|
}
|
|
|
|
else if ("portrait-secondary".equals(aStr)) {
|
|
|
|
return ScreenOrientation.PORTRAIT_SECONDARY;
|
|
|
|
}
|
|
|
|
else if ("landscape-primary".equals(aStr)) {
|
|
|
|
return ScreenOrientation.LANDSCAPE_PRIMARY;
|
|
|
|
}
|
|
|
|
else if ("landscape-secondary".equals(aStr)) {
|
|
|
|
return ScreenOrientation.LANDSCAPE_SECONDARY;
|
|
|
|
}
|
|
|
|
Log.w(LOGTAG, "screenOrientationFromString: unknown orientation string");
|
|
|
|
return DEFAULT_SCREEN_ORIENTATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert Gecko screen orientation to Android orientation.
|
|
|
|
*
|
|
|
|
* @param aScreenOrientation
|
|
|
|
* Gecko screen orientation.
|
|
|
|
* @return Android orientation. This conversion is lossy, the Android
|
|
|
|
* orientation does not differentiate between primary and secondary
|
|
|
|
* orientations.
|
|
|
|
*/
|
|
|
|
public static int screenOrientationToAndroidOrientation(ScreenOrientation aScreenOrientation) {
|
|
|
|
switch (aScreenOrientation) {
|
|
|
|
case PORTRAIT_PRIMARY:
|
|
|
|
case PORTRAIT_SECONDARY:
|
|
|
|
return Configuration.ORIENTATION_PORTRAIT;
|
|
|
|
case LANDSCAPE_PRIMARY:
|
|
|
|
case LANDSCAPE_SECONDARY:
|
|
|
|
return Configuration.ORIENTATION_LANDSCAPE;
|
|
|
|
case NONE:
|
|
|
|
case DEFAULT:
|
|
|
|
default:
|
|
|
|
return Configuration.ORIENTATION_UNDEFINED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert Gecko screen orientation to Android ActivityInfo orientation.
|
|
|
|
* This is yet another orientation used by Android, but it's more detailed
|
|
|
|
* than the Android orientation.
|
|
|
|
* It is required for screen orientation locking and unlocking.
|
|
|
|
*
|
|
|
|
* @param aScreenOrientation
|
|
|
|
* Gecko screen orientation.
|
|
|
|
* @return Android ActivityInfo orientation.
|
|
|
|
*/
|
|
|
|
public static int screenOrientationToActivityInfoOrientation(ScreenOrientation aScreenOrientation) {
|
|
|
|
switch (aScreenOrientation) {
|
|
|
|
case PORTRAIT_PRIMARY:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
|
|
|
case PORTRAIT_SECONDARY:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
|
|
|
|
case LANDSCAPE_PRIMARY:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
|
|
|
case LANDSCAPE_SECONDARY:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
|
|
|
|
case DEFAULT:
|
|
|
|
case NONE:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
|
|
|
default:
|
|
|
|
return ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|