From 2ef46ed28b28b355d7f3f1432c7b1196b832a859 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Tue, 8 May 2012 17:57:33 +0800 Subject: [PATCH] Better orientation change handling. Bug 6451117: Preview location is wrong after rotating the device quickly Bug 6444303: The preview location is wrong when camera is started upside down on tablet Bug 6451710: Tap to focus broken in landscape Change-Id: I12fd57d6618ec5521ccc6efcbf65de57ff2ea3d2 --- src/com/android/gallery3d/app/AppBridge.java | 2 +- .../android/gallery3d/app/OrientationManager.java | 15 +++-- src/com/android/gallery3d/app/PhotoPage.java | 18 ++---- src/com/android/gallery3d/ui/GLRoot.java | 6 +- src/com/android/gallery3d/ui/GLRootView.java | 50 ++++++++++----- src/com/android/gallery3d/ui/GLView.java | 23 ++----- .../android/gallery3d/ui/OrientationSource.java | 22 +++++++ src/com/android/gallery3d/ui/PhotoView.java | 75 ++++++++++++++-------- tests/src/com/android/gallery3d/ui/GLRootMock.java | 6 +- tests/src/com/android/gallery3d/ui/GLRootStub.java | 6 +- 10 files changed, 142 insertions(+), 81 deletions(-) create mode 100644 src/com/android/gallery3d/ui/OrientationSource.java diff --git a/src/com/android/gallery3d/app/AppBridge.java b/src/com/android/gallery3d/app/AppBridge.java index 598361b98..e8cf8731b 100644 --- a/src/com/android/gallery3d/app/AppBridge.java +++ b/src/com/android/gallery3d/app/AppBridge.java @@ -50,7 +50,7 @@ public abstract class AppBridge implements Parcelable { public interface Server { // Set the camera frame relative to GLRootView. - public void setCameraNaturalFrame(Rect frame); + public void setCameraRelativeFrame(Rect frame); // Switch to the previous or next picture using the capture animation. // The offset is -1 to switch to the previous picture, 1 to switch to // the next picture. diff --git a/src/com/android/gallery3d/app/OrientationManager.java b/src/com/android/gallery3d/app/OrientationManager.java index a54f66840..a11977526 100644 --- a/src/com/android/gallery3d/app/OrientationManager.java +++ b/src/com/android/gallery3d/app/OrientationManager.java @@ -24,13 +24,15 @@ import android.view.OrientationEventListener; import android.view.Surface; import android.view.ViewConfiguration; +import com.android.gallery3d.ui.OrientationSource; + import java.util.ArrayList; -public class OrientationManager { +public class OrientationManager implements OrientationSource { private static final String TAG = "OrientationManager"; public interface Listener { - public void onOrientationCompensationChanged(int degrees); + public void onOrientationCompensationChanged(); } // Orientation hysteresis amount used in rounding, in degrees @@ -139,8 +141,7 @@ public class OrientationManager { private void notifyListeners() { synchronized (mListeners) { for (int i = 0, n = mListeners.size(); i < n; i++) { - mListeners.get(i).onOrientationCompensationChanged( - mOrientationCompensation); + mListeners.get(i).onOrientationCompensationChanged(); } } } @@ -164,10 +165,16 @@ public class OrientationManager { } } + @Override public int getDisplayRotation() { return getDisplayRotation(mActivity); } + @Override + public int getCompensation() { + return mOrientationCompensation; + } + private static int roundOrientation(int orientation, int orientationHistory) { boolean changeOrientation = false; if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) { diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index 2ecf5f309..783d0ed25 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -153,14 +153,6 @@ public class PhotoPage extends ActivityState implements mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom); } } - - @Override - protected void orient(int displayRotation, int compensation) { - displayRotation = mOrientationManager.getDisplayRotation(); - Log.d(TAG, "orient -- display rotation " + displayRotation - + ", compensation = " + compensation); - super.orient(displayRotation, compensation); - } }; @Override @@ -175,6 +167,7 @@ public class PhotoPage extends ActivityState implements mApplication = (GalleryApp)((Activity) mActivity).getApplication(); mOrientationManager = mActivity.getOrientationManager(); mOrientationManager.addListener(this); + mActivity.getGLRoot().setOrientationSource(mOrientationManager); mSetPathString = data.getString(KEY_MEDIA_SET_PATH); mOriginalSetPathString = mSetPathString; @@ -426,8 +419,8 @@ public class PhotoPage extends ActivityState implements } @Override - public void onOrientationCompensationChanged(int degrees) { - mActivity.getGLRoot().setOrientationCompensation(degrees); + public void onOrientationCompensationChanged() { + mActivity.getGLRoot().requestLayoutContentPane(); } @Override @@ -482,8 +475,8 @@ public class PhotoPage extends ActivityState implements ////////////////////////////////////////////////////////////////////////// @Override - public void setCameraNaturalFrame(Rect frame) { - mPhotoView.setCameraNaturalFrame(frame); + public void setCameraRelativeFrame(Rect frame) { + mPhotoView.setCameraRelativeFrame(frame); } @Override @@ -758,6 +751,7 @@ public class PhotoPage extends ActivityState implements mScreenNail = null; } mOrientationManager.removeListener(this); + mActivity.getGLRoot().setOrientationSource(null); // Remove all pending messages. mHandler.removeCallbacksAndMessages(null); diff --git a/src/com/android/gallery3d/ui/GLRoot.java b/src/com/android/gallery3d/ui/GLRoot.java index 753f73c4b..313d81a5f 100644 --- a/src/com/android/gallery3d/ui/GLRoot.java +++ b/src/com/android/gallery3d/ui/GLRoot.java @@ -16,6 +16,7 @@ package com.android.gallery3d.ui; +import android.graphics.Matrix; import com.android.gallery3d.anim.CanvasAnimation; public interface GLRoot { @@ -36,5 +37,8 @@ public interface GLRoot { public void unlockRenderThread(); public void setContentPane(GLView content); - public void setOrientationCompensation(int degrees); + public void setOrientationSource(OrientationSource source); + public int getDisplayRotation(); + public int getCompensation(); + public Matrix getCompensationMatrix(); } diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java index f063b84dd..7f8f1f4ff 100644 --- a/src/com/android/gallery3d/ui/GLRootView.java +++ b/src/com/android/gallery3d/ui/GLRootView.java @@ -70,12 +70,15 @@ public class GLRootView extends GLSurfaceView private GLCanvas mCanvas; private GLView mContentView; + private OrientationSource mOrientationSource; // mCompensation is the difference between the UI orientation on GLCanvas // and the framework orientation. See OrientationManager for details. private int mCompensation; // mCompensationMatrix maps the coordinates of touch events. It is kept sync // with mCompensation. private Matrix mCompensationMatrix = new Matrix(); + private int mDisplayRotation; + // The value which will become mCompensation in next layout. private int mPendingCompensation; @@ -187,11 +190,20 @@ public class GLRootView extends GLSurfaceView int w = getWidth(); int h = getHeight(); + int displayRotation = 0; + int compensation = 0; + + // Get the new orientation values + if (mOrientationSource != null) { + displayRotation = mOrientationSource.getDisplayRotation(); + compensation = mOrientationSource.getCompensation(); + } else { + displayRotation = 0; + compensation = 0; + } - // Before doing layout, if there is a compensation change pending, update - // mCompensation and mCompensationMatrix. - if (mCompensation != mPendingCompensation) { - mCompensation = mPendingCompensation; + if (mCompensation != compensation) { + mCompensation = compensation; if (mCompensation % 180 != 0) { mCompensationMatrix.setRotate(mCompensation); // move center to origin before rotation @@ -202,14 +214,7 @@ public class GLRootView extends GLSurfaceView mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2); } } - - // Tell the views about current display rotation and compensation value. - if (mContentView != null) { - // This is a hack: note the 0 should be the display rotation, but we - // don't know the display rotation here. The PhotoPage will inject - // the correct value in its mRootPane.orient() method. - mContentView.orient(0, mCompensation); - } + mDisplayRotation = displayRotation; // Do the actual layout. if (mCompensation % 180 != 0) { @@ -463,9 +468,22 @@ public class GLRootView extends GLSurfaceView } @Override - public void setOrientationCompensation(int degrees) { - if (mPendingCompensation == degrees) return; - mPendingCompensation = degrees; - requestLayoutContentPane(); + public void setOrientationSource(OrientationSource source) { + mOrientationSource = source; + } + + @Override + public int getDisplayRotation() { + return mDisplayRotation; + } + + @Override + public int getCompensation() { + return mCompensation; + } + + @Override + public Matrix getCompensationMatrix() { + return mCompensationMatrix; } } diff --git a/src/com/android/gallery3d/ui/GLView.java b/src/com/android/gallery3d/ui/GLView.java index ec29939e7..bb71312fb 100644 --- a/src/com/android/gallery3d/ui/GLView.java +++ b/src/com/android/gallery3d/ui/GLView.java @@ -305,13 +305,12 @@ public class GLView { public void layout(int left, int top, int right, int bottom) { boolean sizeChanged = setBounds(left, top, right, bottom); - if (sizeChanged) { - mViewFlags &= ~FLAG_LAYOUT_REQUESTED; - onLayout(true, left, top, right, bottom); - } else if ((mViewFlags & FLAG_LAYOUT_REQUESTED)!= 0) { - mViewFlags &= ~FLAG_LAYOUT_REQUESTED; - onLayout(false, left, top, right, bottom); - } + mViewFlags &= ~FLAG_LAYOUT_REQUESTED; + // We call onLayout no matter sizeChanged is true or not because the + // orientation may change without changing the size of the View (for + // example, rotate the device by 180 degrees), and we want to handle + // orientation change in onLayout. + onLayout(sizeChanged, left, top, right, bottom); } private boolean setBounds(int left, int top, int right, int bottom) { @@ -359,16 +358,6 @@ public class GLView { boolean changeSize, int left, int top, int right, int bottom) { } - protected void orient(int displayRotation, int compensation) { - onOrient(displayRotation, compensation); - for (int i = 0, n = getComponentCount(); i < n; ++i) { - getComponent(i).orient(displayRotation, compensation); - } - } - - protected void onOrient(int displayRotation, int compensation) { - } - /** * Gets the bounds of the given descendant that relative to this view. */ diff --git a/src/com/android/gallery3d/ui/OrientationSource.java b/src/com/android/gallery3d/ui/OrientationSource.java new file mode 100644 index 000000000..e13ce1cec --- /dev/null +++ b/src/com/android/gallery3d/ui/OrientationSource.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.ui; + +public interface OrientationSource { + public int getDisplayRotation(); + public int getCompensation(); +} diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index 7b7c8325b..3c90d9982 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -18,6 +18,7 @@ package com.android.gallery3d.ui; import android.content.Context; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.Message; @@ -168,7 +169,7 @@ public class PhotoView extends GLView { private int mDisplayRotation = 0; private int mCompensation = 0; private boolean mFullScreen = true; - private Rect mCameraNaturalFrame = new Rect(); + private Rect mCameraRelativeFrame = new Rect(); private Rect mCameraRect = new Rect(); // [mPrevBound, mNextBound] is the range of index for all pictures in the @@ -361,25 +362,32 @@ public class PhotoView extends GLView { } @Override - protected void onOrient(int displayRotation, int compensation) { - // onLayout will be called soon. We need to change the size and rotation - // of the Camera ScreenNail, but we don't want it start moving because - // the view size will be changed soon. - mDisplayRotation = displayRotation; - mCompensation = compensation; - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - Picture p = mPictures.get(i); - if (p.isCamera()) { - p.updateSize(true); + protected void onLayout( + boolean changeSize, int left, int top, int right, int bottom) { + int w = right - left; + int h = bottom - top; + mTileView.layout(0, 0, w, h); + mEdgeView.layout(0, 0, w, h); + + GLRoot root = getGLRoot(); + int displayRotation = root.getDisplayRotation(); + int compensation = root.getCompensation(); + if (mDisplayRotation != displayRotation + || mCompensation != compensation) { + mDisplayRotation = displayRotation; + mCompensation = compensation; + + // We need to change the size and rotation of the Camera ScreenNail, but + // we don't want it to animate because the size doen't actually + // change in the eye of the user. + for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { + Picture p = mPictures.get(i); + if (p.isCamera()) { + p.updateSize(true); + } } } - } - @Override - protected void onLayout( - boolean changeSize, int left, int top, int right, int bottom) { - mTileView.layout(left, top, right, bottom); - mEdgeView.layout(left, top, right, bottom); updateConstrainedFrame(); if (changeSize) { mPositionController.setViewSize(getWidth(), getHeight()); @@ -388,32 +396,37 @@ public class PhotoView extends GLView { // Update the constrained frame due to layout change. private void updateConstrainedFrame() { + // Get the width and height in framework orientation because the given + // mCameraRelativeFrame is in that coordinates. int w = getWidth(); int h = getHeight(); - int rotation = getCameraRotation(); - if (rotation % 180 != 0) { + if (mCompensation % 180 != 0) { int tmp = w; w = h; h = tmp; } + int l = mCameraRelativeFrame.left; + int t = mCameraRelativeFrame.top; + int r = mCameraRelativeFrame.right; + int b = mCameraRelativeFrame.bottom; - int l = mCameraNaturalFrame.left; - int t = mCameraNaturalFrame.top; - int r = mCameraNaturalFrame.right; - int b = mCameraNaturalFrame.bottom; - - switch (rotation) { + // Now convert it to the coordinates we are using. + switch (mCompensation) { case 0: mCameraRect.set(l, t, r, b); break; case 90: mCameraRect.set(h - b, l, h - t, r); break; case 180: mCameraRect.set(w - r, h - b, w - l, h - t); break; case 270: mCameraRect.set(t, w - r, b, w - l); break; } + Log.d(TAG, "compensation = " + mCompensation + + ", CameraRelativeFrame = " + mCameraRelativeFrame + + ", mCameraRect = " + mCameraRect); mPositionController.setConstrainedFrame(mCameraRect); } - public void setCameraNaturalFrame(Rect frame) { - mCameraNaturalFrame.set(frame); + public void setCameraRelativeFrame(Rect frame) { + mCameraRelativeFrame.set(frame); + updateConstrainedFrame(); } // Returns the rotation we need to do to the camera texture before drawing @@ -802,7 +815,13 @@ public class PhotoView extends GLView { } if (mListener != null) { - mListener.onSingleTapUp((int) x, (int) y); + // Do the inverse transform of the touch coordinates. + Matrix m = getGLRoot().getCompensationMatrix(); + Matrix inv = new Matrix(); + m.invert(inv); + float[] pts = new float[] {x, y}; + inv.mapPoints(pts); + mListener.onSingleTapUp((int) (pts[0] + 0.5f), (int) (pts[1] + 0.5f)); } return true; } diff --git a/tests/src/com/android/gallery3d/ui/GLRootMock.java b/tests/src/com/android/gallery3d/ui/GLRootMock.java index 55f1c9a12..4af7a1f59 100644 --- a/tests/src/com/android/gallery3d/ui/GLRootMock.java +++ b/tests/src/com/android/gallery3d/ui/GLRootMock.java @@ -16,6 +16,7 @@ package com.android.gallery3d.ui; +import android.graphics.Matrix; import com.android.gallery3d.anim.CanvasAnimation; public class GLRootMock implements GLRoot { @@ -34,5 +35,8 @@ public class GLRootMock implements GLRoot { public void lockRenderThread() {} public void unlockRenderThread() {} public void setContentPane(GLView content) {} - public void setOrientationCompensation(int degrees) {} + public void setOrientationSource(OrientationSource source) {} + public int getDisplayRotation() { return 0; } + public int getCompensation() { return 0; } + public Matrix getCompensationMatrix() { return null; } } diff --git a/tests/src/com/android/gallery3d/ui/GLRootStub.java b/tests/src/com/android/gallery3d/ui/GLRootStub.java index bf9b63f6b..878eeddb4 100644 --- a/tests/src/com/android/gallery3d/ui/GLRootStub.java +++ b/tests/src/com/android/gallery3d/ui/GLRootStub.java @@ -16,6 +16,7 @@ package com.android.gallery3d.ui; +import android.graphics.Matrix; import com.android.gallery3d.anim.CanvasAnimation; public class GLRootStub implements GLRoot { @@ -27,5 +28,8 @@ public class GLRootStub implements GLRoot { public void lockRenderThread() {} public void unlockRenderThread() {} public void setContentPane(GLView content) {} - public void setOrientationCompensation(int degrees) {} + public void setOrientationSource(OrientationSource source) {} + public int getDisplayRotation() { return 0; } + public int getCompensation() { return 0; } + public Matrix getCompensationMatrix() { return null; } } -- 2.11.0