Loading quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +69 −35 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; Loading @@ -38,11 +37,11 @@ import android.graphics.Shader; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Property; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; Loading Loading @@ -102,7 +101,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private float mSaturation = 1f; private boolean mOverlayEnabled; private boolean mRotated; private boolean mIsOrientationChanged; private OverviewScreenshotActions mOverviewScreenshotActionsPlugin; public TaskThumbnailView(Context context) { Loading Loading @@ -323,7 +322,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private void updateOverlay() { // The overlay doesn't really work when the screenshot is rotated, so don't add it. if (mOverlayEnabled && !mRotated && mBitmapShader != null && mThumbnailData != null) { if (mOverlayEnabled && !mIsOrientationChanged && mBitmapShader != null && mThumbnailData != null) { mOverlay.initOverlay(mTask, mThumbnailData, mMatrix); } else { mOverlay.reset(); Loading @@ -346,6 +345,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private void updateThumbnailMatrix() { boolean isRotated = false; boolean isOrientationDifferent = false; mClipBottom = -1; if (mBitmapShader != null && mThumbnailData != null) { float scale = mThumbnailData.scale; Loading @@ -356,51 +356,40 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc (thumbnailInsets.top + thumbnailInsets.bottom) * scale; final float thumbnailScale; final DeviceProfile profile = mActivity.getDeviceProfile(); int thumbnailRotation = mThumbnailData.rotation; int currentRotation = getDisplay() != null ? getDisplay().getRotation() : 0; int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation); // Landscape vs portrait change boolean windowingModeSupportsRotation = !mActivity.isInMultiWindowMode() && mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; isOrientationDifferent = isOrientationChange(deltaRotate) && windowingModeSupportsRotation; if (getMeasuredWidth() == 0) { // If we haven't measured , skip the thumbnail drawing and only draw the background // color thumbnailScale = 0f; } else { final Configuration configuration = getContext().getResources().getConfiguration(); // Rotate the screenshot if not in multi-window mode isRotated = configuration.orientation != mThumbnailData.orientation && !mActivity.isInMultiWindowMode() && mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; isRotated = deltaRotate > 0 && windowingModeSupportsRotation; // Scale the screenshot to always fit the width of the card. thumbnailScale = isRotated thumbnailScale = isOrientationDifferent ? getMeasuredWidth() / thumbnailHeight : getMeasuredWidth() / thumbnailWidth; } if (isRotated) { int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1; mMatrix.setRotate(90 * rotationDir); int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top; int newTopInset = rotationDir == 1 ? thumbnailInsets.left : thumbnailInsets.right; mClippedInsets.offsetTo(newLeftInset * scale, newTopInset * scale); if (rotationDir == -1) { // Crop the right/bottom side of the screenshot rather than left/top float excessHeight = thumbnailWidth * thumbnailScale - getMeasuredHeight(); mClippedInsets.offset(0, excessHeight); } mMatrix.postTranslate(-mClippedInsets.left, -mClippedInsets.top); // Move the screenshot to the thumbnail window (rotation moved it out). if (rotationDir == 1) { mMatrix.postTranslate(mThumbnailData.thumbnail.getHeight(), 0); } else { mMatrix.postTranslate(0, mThumbnailData.thumbnail.getWidth()); } } else { mClippedInsets.offsetTo(thumbnailInsets.left * scale, thumbnailInsets.top * scale); if (!isRotated) { // No Rotation mClippedInsets.offsetTo(thumbnailInsets.left * scale, thumbnailInsets.top * scale); mMatrix.setTranslate(-mClippedInsets.left, -mClippedInsets.top); } else { setThumbnailRotation(deltaRotate, thumbnailInsets, scale); } final float widthWithInsets; final float heightWithInsets; if (isRotated) { if (isOrientationDifferent) { widthWithInsets = mThumbnailData.thumbnail.getHeight() * thumbnailScale; heightWithInsets = mThumbnailData.thumbnail.getWidth() * thumbnailScale; } else { Loading @@ -415,7 +404,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc mMatrix.postScale(thumbnailScale, thumbnailScale); mBitmapShader.setLocalMatrix(mMatrix); float bitmapHeight = Math.max((isRotated ? thumbnailWidth : thumbnailHeight) float bitmapHeight = Math.max((isOrientationDifferent ? thumbnailWidth : thumbnailHeight) * thumbnailScale, 0); if (Math.round(bitmapHeight) < getMeasuredHeight()) { mClipBottom = bitmapHeight; Loading @@ -423,7 +412,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc mPaint.setShader(mBitmapShader); } mRotated = isRotated; mIsOrientationChanged = isOrientationDifferent; invalidate(); // Update can be called from {@link #onSizeChanged} during layout, post handling of overlay Loading @@ -431,6 +420,51 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc post(this::updateOverlay); } private int getRotationDelta(int oldRotation, int newRotation) { int delta = newRotation - oldRotation; if (delta < 0) delta += 4; return delta; } /** * @param deltaRotation the number of 90 degree turns from the current orientation * @return {@code true} if the change in rotation results in a shift from landscape to portrait * or vice versa, {@code false} otherwise */ private boolean isOrientationChange(int deltaRotation) { return deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270; } private void setThumbnailRotation(int deltaRotate, Rect thumbnailInsets, float scale) { int newLeftInset = 0; int newTopInset = 0; int translateX = 0; int translateY = 0; mMatrix.setRotate(90 * deltaRotate); switch (deltaRotate) { /* Counter-clockwise */ case Surface.ROTATION_90: newLeftInset = thumbnailInsets.bottom; newTopInset = thumbnailInsets.left; translateX = mThumbnailData.thumbnail.getHeight(); break; case Surface.ROTATION_270: newLeftInset = thumbnailInsets.top; newTopInset = thumbnailInsets.right; translateY = mThumbnailData.thumbnail.getWidth(); break; case Surface.ROTATION_180: newLeftInset = -thumbnailInsets.top; newTopInset = -thumbnailInsets.left; translateX = mThumbnailData.thumbnail.getWidth(); translateY = mThumbnailData.thumbnail.getHeight(); break; } mClippedInsets.offsetTo(newLeftInset * scale, newTopInset * scale); mMatrix.postTranslate(translateX - mClippedInsets.left, translateY - mClippedInsets.top); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Loading Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +69 −35 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; Loading @@ -38,11 +37,11 @@ import android.graphics.Shader; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Property; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; Loading Loading @@ -102,7 +101,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private float mSaturation = 1f; private boolean mOverlayEnabled; private boolean mRotated; private boolean mIsOrientationChanged; private OverviewScreenshotActions mOverviewScreenshotActionsPlugin; public TaskThumbnailView(Context context) { Loading Loading @@ -323,7 +322,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private void updateOverlay() { // The overlay doesn't really work when the screenshot is rotated, so don't add it. if (mOverlayEnabled && !mRotated && mBitmapShader != null && mThumbnailData != null) { if (mOverlayEnabled && !mIsOrientationChanged && mBitmapShader != null && mThumbnailData != null) { mOverlay.initOverlay(mTask, mThumbnailData, mMatrix); } else { mOverlay.reset(); Loading @@ -346,6 +345,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc private void updateThumbnailMatrix() { boolean isRotated = false; boolean isOrientationDifferent = false; mClipBottom = -1; if (mBitmapShader != null && mThumbnailData != null) { float scale = mThumbnailData.scale; Loading @@ -356,51 +356,40 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc (thumbnailInsets.top + thumbnailInsets.bottom) * scale; final float thumbnailScale; final DeviceProfile profile = mActivity.getDeviceProfile(); int thumbnailRotation = mThumbnailData.rotation; int currentRotation = getDisplay() != null ? getDisplay().getRotation() : 0; int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation); // Landscape vs portrait change boolean windowingModeSupportsRotation = !mActivity.isInMultiWindowMode() && mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; isOrientationDifferent = isOrientationChange(deltaRotate) && windowingModeSupportsRotation; if (getMeasuredWidth() == 0) { // If we haven't measured , skip the thumbnail drawing and only draw the background // color thumbnailScale = 0f; } else { final Configuration configuration = getContext().getResources().getConfiguration(); // Rotate the screenshot if not in multi-window mode isRotated = configuration.orientation != mThumbnailData.orientation && !mActivity.isInMultiWindowMode() && mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; isRotated = deltaRotate > 0 && windowingModeSupportsRotation; // Scale the screenshot to always fit the width of the card. thumbnailScale = isRotated thumbnailScale = isOrientationDifferent ? getMeasuredWidth() / thumbnailHeight : getMeasuredWidth() / thumbnailWidth; } if (isRotated) { int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1; mMatrix.setRotate(90 * rotationDir); int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top; int newTopInset = rotationDir == 1 ? thumbnailInsets.left : thumbnailInsets.right; mClippedInsets.offsetTo(newLeftInset * scale, newTopInset * scale); if (rotationDir == -1) { // Crop the right/bottom side of the screenshot rather than left/top float excessHeight = thumbnailWidth * thumbnailScale - getMeasuredHeight(); mClippedInsets.offset(0, excessHeight); } mMatrix.postTranslate(-mClippedInsets.left, -mClippedInsets.top); // Move the screenshot to the thumbnail window (rotation moved it out). if (rotationDir == 1) { mMatrix.postTranslate(mThumbnailData.thumbnail.getHeight(), 0); } else { mMatrix.postTranslate(0, mThumbnailData.thumbnail.getWidth()); } } else { mClippedInsets.offsetTo(thumbnailInsets.left * scale, thumbnailInsets.top * scale); if (!isRotated) { // No Rotation mClippedInsets.offsetTo(thumbnailInsets.left * scale, thumbnailInsets.top * scale); mMatrix.setTranslate(-mClippedInsets.left, -mClippedInsets.top); } else { setThumbnailRotation(deltaRotate, thumbnailInsets, scale); } final float widthWithInsets; final float heightWithInsets; if (isRotated) { if (isOrientationDifferent) { widthWithInsets = mThumbnailData.thumbnail.getHeight() * thumbnailScale; heightWithInsets = mThumbnailData.thumbnail.getWidth() * thumbnailScale; } else { Loading @@ -415,7 +404,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc mMatrix.postScale(thumbnailScale, thumbnailScale); mBitmapShader.setLocalMatrix(mMatrix); float bitmapHeight = Math.max((isRotated ? thumbnailWidth : thumbnailHeight) float bitmapHeight = Math.max((isOrientationDifferent ? thumbnailWidth : thumbnailHeight) * thumbnailScale, 0); if (Math.round(bitmapHeight) < getMeasuredHeight()) { mClipBottom = bitmapHeight; Loading @@ -423,7 +412,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc mPaint.setShader(mBitmapShader); } mRotated = isRotated; mIsOrientationChanged = isOrientationDifferent; invalidate(); // Update can be called from {@link #onSizeChanged} during layout, post handling of overlay Loading @@ -431,6 +420,51 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc post(this::updateOverlay); } private int getRotationDelta(int oldRotation, int newRotation) { int delta = newRotation - oldRotation; if (delta < 0) delta += 4; return delta; } /** * @param deltaRotation the number of 90 degree turns from the current orientation * @return {@code true} if the change in rotation results in a shift from landscape to portrait * or vice versa, {@code false} otherwise */ private boolean isOrientationChange(int deltaRotation) { return deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270; } private void setThumbnailRotation(int deltaRotate, Rect thumbnailInsets, float scale) { int newLeftInset = 0; int newTopInset = 0; int translateX = 0; int translateY = 0; mMatrix.setRotate(90 * deltaRotate); switch (deltaRotate) { /* Counter-clockwise */ case Surface.ROTATION_90: newLeftInset = thumbnailInsets.bottom; newTopInset = thumbnailInsets.left; translateX = mThumbnailData.thumbnail.getHeight(); break; case Surface.ROTATION_270: newLeftInset = thumbnailInsets.top; newTopInset = thumbnailInsets.right; translateY = mThumbnailData.thumbnail.getWidth(); break; case Surface.ROTATION_180: newLeftInset = -thumbnailInsets.top; newTopInset = -thumbnailInsets.left; translateX = mThumbnailData.thumbnail.getWidth(); translateY = mThumbnailData.thumbnail.getHeight(); break; } mClippedInsets.offsetTo(newLeftInset * scale, newTopInset * scale); mMatrix.postTranslate(translateX - mClippedInsets.left, translateY - mClippedInsets.top); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Loading