mobile/android/base/GeckoScreenOrientation.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko;
     8 import android.content.Context;
     9 import android.content.pm.ActivityInfo;
    10 import android.content.res.Configuration;
    11 import android.util.Log;
    12 import android.view.Surface;
    13 import android.app.Activity;
    15 import java.util.Arrays;
    16 import java.util.List;
    18 /*
    19  * Updates, locks and unlocks the screen orientation.
    20  *
    21  * Note: Replaces the OnOrientationChangeListener to avoid redundant rotation
    22  * event handling.
    23  */
    24 public class GeckoScreenOrientation {
    25     private static final String LOGTAG = "GeckoScreenOrientation";
    27     // Make sure that any change in dom/base/ScreenOrientation.h happens here too.
    28     public enum ScreenOrientation {
    29         NONE(0),
    30         PORTRAIT_PRIMARY(1 << 0),
    31         PORTRAIT_SECONDARY(1 << 1),
    32         LANDSCAPE_PRIMARY(1 << 2),
    33         LANDSCAPE_SECONDARY(1 << 3),
    34         DEFAULT(1 << 4);
    36         public final short value;
    38         private ScreenOrientation(int value) {
    39             this.value = (short)value;
    40         }
    42         public static ScreenOrientation get(short value) {
    43             switch (value) {
    44                 case (1 << 0): return PORTRAIT_PRIMARY;
    45                 case (1 << 1): return PORTRAIT_SECONDARY;
    46                 case (1 << 2): return LANDSCAPE_PRIMARY;
    47                 case (1 << 3): return LANDSCAPE_SECONDARY;
    48                 case (1 << 4): return DEFAULT;
    49                 default: return NONE;
    50             }
    51         }
    52     }
    54     // Singleton instance.
    55     private static GeckoScreenOrientation sInstance = null;
    56     // Default screen orientation, used for initialization and unlocking.
    57     private static final ScreenOrientation DEFAULT_SCREEN_ORIENTATION = ScreenOrientation.DEFAULT;
    58     // Default rotation, used when device rotation is unknown.
    59     private static final int DEFAULT_ROTATION = Surface.ROTATION_0;
    60     // Default orientation, used if screen orientation is unspecified.
    61     private ScreenOrientation mDefaultScreenOrientation;
    62     // Last updated screen orientation.
    63     private ScreenOrientation mScreenOrientation;
    64     // Whether the update should notify Gecko about screen orientation changes.
    65     private boolean mShouldNotify = true;
    66     // Configuration screen orientation preference path.
    67     private static final String DEFAULT_SCREEN_ORIENTATION_PREF = "app.orientation.default";
    69     public GeckoScreenOrientation() {
    70         PrefsHelper.getPref(DEFAULT_SCREEN_ORIENTATION_PREF, new PrefsHelper.PrefHandlerBase() {
    71             @Override public void prefValue(String pref, String value) {
    72                 // Read and update the configuration default preference.
    73                 mDefaultScreenOrientation = screenOrientationFromArrayString(value);
    74                 setRequestedOrientation(mDefaultScreenOrientation);
    75             }
    76         });
    78         mDefaultScreenOrientation = DEFAULT_SCREEN_ORIENTATION;
    79         update();
    80     }
    82     public static GeckoScreenOrientation getInstance() {
    83         if (sInstance == null) {
    84             sInstance = new GeckoScreenOrientation();
    85         }
    86         return sInstance;
    87     }
    89     /*
    90      * Enable Gecko screen orientation events on update.
    91      */
    92     public void enableNotifications() {
    93         update();
    94         mShouldNotify = true;
    95     }
    97     /*
    98      * Disable Gecko screen orientation events on update.
    99      */
   100     public void disableNotifications() {
   101         mShouldNotify = false;
   102     }
   104     /*
   105      * Update screen orientation.
   106      * Retrieve orientation and rotation via GeckoAppShell.
   107      *
   108      * @return Whether the screen orientation has changed.
   109      */
   110     public boolean update() {
   111         Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
   112         if (activity == null) {
   113             return false;
   114         }
   115         Configuration config = activity.getResources().getConfiguration();
   116         return update(config.orientation);
   117     }
   119     /*
   120      * Update screen orientation given the android orientation.
   121      * Retrieve rotation via GeckoAppShell.
   122      *
   123      * @param aAndroidOrientation
   124      *        Android screen orientation from Configuration.orientation.
   125      *
   126      * @return Whether the screen orientation has changed.
   127      */
   128     public boolean update(int aAndroidOrientation) {
   129         return update(getScreenOrientation(aAndroidOrientation, getRotation()));
   130     }
   132     /*
   133      * Update screen orientation given the screen orientation.
   134      *
   135      * @param aScreenOrientation
   136      *        Gecko screen orientation based on android orientation and rotation.
   137      *
   138      * @return Whether the screen orientation has changed.
   139      */
   140     public boolean update(ScreenOrientation aScreenOrientation) {
   141         if (mScreenOrientation == aScreenOrientation) {
   142             return false;
   143         }
   144         mScreenOrientation = aScreenOrientation;
   145         Log.d(LOGTAG, "updating to new orientation " + mScreenOrientation);
   146         if (mShouldNotify) {
   147             GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenOrientationEvent(mScreenOrientation.value));
   148         }
   149         return true;
   150     }
   152     /*
   153      * @return The Android orientation (Configuration.orientation).
   154      */
   155     public int getAndroidOrientation() {
   156         return screenOrientationToAndroidOrientation(getScreenOrientation());
   157     }
   159     /*
   160      * @return The Gecko screen orientation derived from Android orientation and
   161      *         rotation.
   162      */
   163     public ScreenOrientation getScreenOrientation() {
   164         return mScreenOrientation;
   165     }
   167     /*
   168      * Lock screen orientation given the Android orientation.
   169      * Retrieve rotation via GeckoAppShell.
   170      *
   171      * @param aAndroidOrientation
   172      *        The Android orientation provided by Configuration.orientation.
   173      */
   174     public void lock(int aAndroidOrientation) {
   175         lock(getScreenOrientation(aAndroidOrientation, getRotation()));
   176     }
   178     /*
   179      * Lock screen orientation given the Gecko screen orientation.
   180      * Retrieve rotation via GeckoAppShell.
   181      *
   182      * @param aScreenOrientation
   183      *        Gecko screen orientation derived from Android orientation and
   184      *        rotation.
   185      *
   186      * @return Whether the locking was successful.
   187      */
   188     public boolean lock(ScreenOrientation aScreenOrientation) {
   189         Log.d(LOGTAG, "locking to " + aScreenOrientation);
   190         update(aScreenOrientation);
   191         return setRequestedOrientation(aScreenOrientation);
   192     }
   194     /*
   195      * Unlock and update screen orientation.
   196      *
   197      * @return Whether the unlocking was successful.
   198      */
   199     public boolean unlock() {
   200         Log.d(LOGTAG, "unlocking");
   201         setRequestedOrientation(mDefaultScreenOrientation);
   202         return update();
   203     }
   205     /*
   206      * Set the given requested orientation for the current activity.
   207      * This is essentially an unlock without an update.
   208      *
   209      * @param aScreenOrientation
   210      *        Gecko screen orientation.
   211      *
   212      * @return Whether the requested orientation was set. This can only fail if
   213      *         the current activity cannot be retrieved vie GeckoAppShell.
   214      *
   215      */
   216     private boolean setRequestedOrientation(ScreenOrientation aScreenOrientation) {
   217         int activityOrientation = screenOrientationToActivityInfoOrientation(aScreenOrientation);
   218         Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
   219         if (activity == null) {
   220             Log.w(LOGTAG, "setRequestOrientation: failed to get activity");
   221         }
   222         if (activity.getRequestedOrientation() == activityOrientation) {
   223             return false;
   224         }
   225         activity.setRequestedOrientation(activityOrientation);
   226         return true;
   227     }
   229     /*
   230      * Combine the Android orientation and rotation to the Gecko orientation.
   231      *
   232      * @param aAndroidOrientation
   233      *        Android orientation from Configuration.orientation.
   234      * @param aRotation
   235      *        Device rotation from Display.getRotation().
   236      *
   237      * @return Gecko screen orientation.
   238      */
   239     private ScreenOrientation getScreenOrientation(int aAndroidOrientation, int aRotation) {
   240         boolean isPrimary = aRotation == Surface.ROTATION_0 || aRotation == Surface.ROTATION_90;
   241         if (aAndroidOrientation == Configuration.ORIENTATION_PORTRAIT) {
   242             if (isPrimary) {
   243                 // Non-rotated portrait device or landscape device rotated
   244                 // to primary portrait mode counter-clockwise.
   245                 return ScreenOrientation.PORTRAIT_PRIMARY;
   246             }
   247             return ScreenOrientation.PORTRAIT_SECONDARY;
   248         }
   249         if (aAndroidOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   250             if (isPrimary) {
   251                 // Non-rotated landscape device or portrait device rotated
   252                 // to primary landscape mode counter-clockwise.
   253                 return ScreenOrientation.LANDSCAPE_PRIMARY;
   254             }
   255             return ScreenOrientation.LANDSCAPE_SECONDARY;
   256         }
   257         return ScreenOrientation.NONE;
   258     }
   260     /*
   261      * @return Device rotation from Display.getRotation().
   262      */
   263     private int getRotation() {
   264         Activity activity = GeckoAppShell.getGeckoInterface().getActivity();
   265         if (activity == null) {
   266             Log.w(LOGTAG, "getRotation: failed to get activity");
   267             return DEFAULT_ROTATION;
   268         }
   269         return activity.getWindowManager().getDefaultDisplay().getRotation();
   270     }
   272     /*
   273      * Retrieve the screen orientation from an array string.
   274      *
   275      * @param aArray
   276      *        String containing comma-delimited strings.
   277      *
   278      * @return First parsed Gecko screen orientation.
   279      */
   280     public static ScreenOrientation screenOrientationFromArrayString(String aArray) {
   281         List<String> orientations = Arrays.asList(aArray.split(","));
   282         if (orientations.size() == 0) {
   283             // If nothing is listed, return default.
   284             Log.w(LOGTAG, "screenOrientationFromArrayString: no orientation in string");
   285             return DEFAULT_SCREEN_ORIENTATION;
   286         }
   288         // We don't support multiple orientations yet. To avoid developer
   289         // confusion, just take the first one listed.
   290         return screenOrientationFromString(orientations.get(0));
   291     }
   293     /*
   294      * Retrieve the scren orientation from a string.
   295      *
   296      * @param aStr
   297      *        String hopefully containing a screen orientation name.
   298      * @return Gecko screen orientation if matched, DEFAULT_SCREEN_ORIENTATION
   299      *         otherwise.
   300      */
   301     public static ScreenOrientation screenOrientationFromString(String aStr) {
   302         if ("portrait".equals(aStr)) {
   303             return ScreenOrientation.PORTRAIT_PRIMARY;
   304         }
   305         else if ("landscape".equals(aStr)) {
   306             return ScreenOrientation.LANDSCAPE_PRIMARY;
   307         }
   308         else if ("portrait-primary".equals(aStr)) {
   309             return ScreenOrientation.PORTRAIT_PRIMARY;
   310         }
   311         else if ("portrait-secondary".equals(aStr)) {
   312             return ScreenOrientation.PORTRAIT_SECONDARY;
   313         }
   314         else if ("landscape-primary".equals(aStr)) {
   315             return ScreenOrientation.LANDSCAPE_PRIMARY;
   316         }
   317         else if ("landscape-secondary".equals(aStr)) {
   318             return ScreenOrientation.LANDSCAPE_SECONDARY;
   319         }
   320         Log.w(LOGTAG, "screenOrientationFromString: unknown orientation string");
   321         return DEFAULT_SCREEN_ORIENTATION;
   322     }
   324     /*
   325      * Convert Gecko screen orientation to Android orientation.
   326      *
   327      * @param aScreenOrientation
   328      *        Gecko screen orientation.
   329      * @return Android orientation. This conversion is lossy, the Android
   330      *         orientation does not differentiate between primary and secondary
   331      *         orientations.
   332      */
   333     public static int screenOrientationToAndroidOrientation(ScreenOrientation aScreenOrientation) {
   334         switch (aScreenOrientation) {
   335             case PORTRAIT_PRIMARY:
   336             case PORTRAIT_SECONDARY:
   337                 return Configuration.ORIENTATION_PORTRAIT;
   338             case LANDSCAPE_PRIMARY:
   339             case LANDSCAPE_SECONDARY:
   340                 return Configuration.ORIENTATION_LANDSCAPE;
   341             case NONE:
   342             case DEFAULT:
   343             default:
   344                 return Configuration.ORIENTATION_UNDEFINED;
   345         }
   346     }
   349     /*
   350      * Convert Gecko screen orientation to Android ActivityInfo orientation.
   351      * This is yet another orientation used by Android, but it's more detailed
   352      * than the Android orientation.
   353      * It is required for screen orientation locking and unlocking.
   354      *
   355      * @param aScreenOrientation
   356      *        Gecko screen orientation.
   357      * @return Android ActivityInfo orientation.
   358      */
   359     public static int screenOrientationToActivityInfoOrientation(ScreenOrientation aScreenOrientation) {
   360         switch (aScreenOrientation) {
   361             case PORTRAIT_PRIMARY:
   362                 return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
   363             case PORTRAIT_SECONDARY:
   364                 return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
   365             case LANDSCAPE_PRIMARY:
   366                 return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
   367             case LANDSCAPE_SECONDARY:
   368                 return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
   369             case DEFAULT:
   370             case NONE:
   371                 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
   372             default:
   373                 return ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
   374         }
   375     }
   376 }

mercurial