Loading core/java/com/android/internal/policy/DividerSnapAlgorithm.java +64 −12 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ package com.android.internal.policy; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.util.Log; import android.view.Display; import android.view.DisplayInfo; import java.util.ArrayList; Loading Loading @@ -57,6 +61,7 @@ public class DividerSnapAlgorithm { private final ArrayList<SnapTarget> mTargets = new ArrayList<>(); private final Rect mInsets = new Rect(); private final int mSnapMode; private final int mMinimalSizeResizableTask; private final float mFixedRatio; private boolean mIsHorizontalDivision; Loading @@ -70,6 +75,22 @@ public class DividerSnapAlgorithm { private final SnapTarget mDismissEndTarget; private final SnapTarget mMiddleTarget; public static DividerSnapAlgorithm create(Context ctx, Rect insets) { DisplayInfo displayInfo = new DisplayInfo(); ctx.getSystemService(DisplayManager.class).getDisplay( Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo); int dividerWindowWidth = ctx.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_thickness); int dividerInsets = ctx.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_insets); return new DividerSnapAlgorithm(ctx.getResources(), displayInfo.logicalWidth, displayInfo.logicalHeight, dividerWindowWidth - 2 * dividerInsets, ctx.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT, insets); } public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, boolean isHorizontalDivision, Rect insets) { mMinFlingVelocityPxPerSecond = Loading @@ -85,6 +106,8 @@ public class DividerSnapAlgorithm { com.android.internal.R.integer.config_dockedStackDividerSnapMode); mFixedRatio = res.getFraction( com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1); mMinimalSizeResizableTask = res.getDimensionPixelSize( com.android.internal.R.dimen.default_minimal_size_resizable_task); calculateTargets(isHorizontalDivision); mFirstSplitTarget = mTargets.get(1); mLastSplitTarget = mTargets.get(mTargets.size() - 2); Loading @@ -93,6 +116,20 @@ public class DividerSnapAlgorithm { mMiddleTarget = mTargets.get(mTargets.size() / 2); } /** * @return whether it's feasible to enable split screen in the current configuration, i.e. when * snapping in the middle both tasks are larger than the minimal task size. */ public boolean isSplitScreenFeasible() { int statusBarSize = mInsets.top; int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right; int size = mIsHorizontalDivision ? mDisplayHeight : mDisplayWidth; int availableSpace = size - navBarSize - statusBarSize - mDividerSize; return availableSpace / 2 >= mMinimalSizeResizableTask; } public SnapTarget calculateSnapTarget(int position, float velocity) { return calculateSnapTarget(position, velocity, true /* hardDismiss */); } Loading Loading @@ -212,10 +249,10 @@ public class DividerSnapAlgorithm { mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f)); switch (mSnapMode) { case SNAP_MODE_16_9: addRatio16_9Targets(isHorizontalDivision); addRatio16_9Targets(isHorizontalDivision, dividerMax); break; case SNAP_FIXED_RATIO: addFixedDivisionTargets(isHorizontalDivision); addFixedDivisionTargets(isHorizontalDivision, dividerMax); break; case SNAP_ONLY_1_1: addMiddleTarget(isHorizontalDivision); Loading @@ -225,19 +262,24 @@ public class DividerSnapAlgorithm { mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f)); } private void addFixedDivisionTargets(boolean isHorizontalDivision) { private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition, int bottomPosition, int dividerMax) { maybeAddTarget(topPosition, topPosition - mInsets.top); addMiddleTarget(isHorizontalDivision); maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom - (bottomPosition + mDividerSize)); } private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) { int start = isHorizontalDivision ? mInsets.top : mInsets.left; int end = isHorizontalDivision ? mDisplayHeight - mInsets.bottom : mDisplayWidth - mInsets.right; mTargets.add(new SnapTarget((int) (start + mFixedRatio * (end - start)) - mDividerSize / 2, SnapTarget.FLAG_NONE)); addMiddleTarget(isHorizontalDivision); mTargets.add(new SnapTarget((int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2, SnapTarget.FLAG_NONE)); int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2; int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2; addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); } private void addRatio16_9Targets(boolean isHorizontalDivision) { private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) { int start = isHorizontalDivision ? mInsets.top : mInsets.left; int end = isHorizontalDivision ? mDisplayHeight - mInsets.bottom Loading @@ -248,9 +290,19 @@ public class DividerSnapAlgorithm { : mDisplayHeight - mInsets.bottom; float size = 9.0f / 16.0f * (endOther - startOther); int sizeInt = (int) Math.floor(size); mTargets.add(new SnapTarget(start + sizeInt, SnapTarget.FLAG_NONE)); addMiddleTarget(isHorizontalDivision); mTargets.add(new SnapTarget(end - sizeInt - mDividerSize, SnapTarget.FLAG_NONE)); int topPosition = start + sizeInt; int bottomPosition = end - sizeInt - mDividerSize; addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); } /** * Adds a target at {@param position} but only if the area with size of {@param smallerSize} * meets the minimal size requirement. */ private void maybeAddTarget(int position, int smallerSize) { if (smallerSize >= mMinimalSizeResizableTask) { mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE)); } } private void addMiddleTarget(boolean isHorizontalDivision) { Loading core/res/res/values/config.xml +0 −4 Original line number Diff line number Diff line Loading @@ -2421,10 +2421,6 @@ disables NetworkPolicyManagerService's presentation of data-usage notifications. --> <string translatable="false" name="config_networkPolicyNotificationComponent"></string> <!-- The fraction of display size (lower of height and width) that will be used to determine the default minimal size for resizeable tasks. --> <fraction name="config_displayFractionForDefaultMinimalSizeOfResizeableTask">25%</fraction> <!-- The BT name of the keyboard packaged with the device. If this is defined, SystemUI will automatically try to pair with it when the device exits tablet mode. --> <string translatable="false" name="config_packagedKeyboardName"></string> Loading core/res/res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -455,4 +455,7 @@ <item type="fraction" name="docked_stack_divider_fixed_ratio">34.15%</item> <dimen name="resize_shadow_size">5dp</dimen> <!-- The default minimal size of a resizable task, in both dimensions. --> <dimen name="default_minimal_size_resizable_task">220dp</dimen> </resources> core/res/res/values/symbols.xml +1 −1 Original line number Diff line number Diff line Loading @@ -1726,7 +1726,7 @@ <java-symbol type="id" name="replace_app_icon" /> <java-symbol type="id" name="replace_message" /> <java-symbol type="fraction" name="config_dimBehindFadeDuration" /> <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" /> <java-symbol type="dimen" name="default_minimal_size_resizable_task" /> <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" /> <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" /> <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/> Loading packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +19 −1 Original line number Diff line number Diff line Loading @@ -19,15 +19,20 @@ package com.android.systemui.recents.views; import android.app.ActivityManager; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.provider.Settings; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewDebug; import android.widget.Toast; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsImpl; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.ConfigurationChangedEvent; import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent; import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; Loading Loading @@ -81,12 +86,20 @@ public class RecentsViewTouchHandler { private float mDragSlop; private DropTarget mLastDropTarget; private DividerSnapAlgorithm mDividerSnapAlgorithm; private ArrayList<DropTarget> mDropTargets = new ArrayList<>(); private ArrayList<TaskStack.DockState> mVisibleDockStates = new ArrayList<>(); public RecentsViewTouchHandler(RecentsView rv) { mRv = rv; mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop(); updateSnapAlgorithm(); } private void updateSnapAlgorithm() { Rect insets = new Rect(); SystemServicesProxy.getInstance(mRv.getContext()).getStableInsets(insets); mDividerSnapAlgorithm = DividerSnapAlgorithm.create(mRv.getContext(), insets); } /** Loading Loading @@ -150,7 +163,8 @@ public class RecentsViewTouchHandler { mTaskView.setTranslationY(y); mVisibleDockStates.clear(); if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) { if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask() && mDividerSnapAlgorithm.isSplitScreenFeasible()) { if (!event.task.isDockable) { Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message, Toast.LENGTH_SHORT).show(); Loading @@ -176,6 +190,10 @@ public class RecentsViewTouchHandler { mLastDropTarget = null; } public final void onBusEvent(ConfigurationChangedEvent event) { updateSnapAlgorithm(); } /** * Handles dragging touch events */ Loading Loading
core/java/com/android/internal/policy/DividerSnapAlgorithm.java +64 −12 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ package com.android.internal.policy; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.util.Log; import android.view.Display; import android.view.DisplayInfo; import java.util.ArrayList; Loading Loading @@ -57,6 +61,7 @@ public class DividerSnapAlgorithm { private final ArrayList<SnapTarget> mTargets = new ArrayList<>(); private final Rect mInsets = new Rect(); private final int mSnapMode; private final int mMinimalSizeResizableTask; private final float mFixedRatio; private boolean mIsHorizontalDivision; Loading @@ -70,6 +75,22 @@ public class DividerSnapAlgorithm { private final SnapTarget mDismissEndTarget; private final SnapTarget mMiddleTarget; public static DividerSnapAlgorithm create(Context ctx, Rect insets) { DisplayInfo displayInfo = new DisplayInfo(); ctx.getSystemService(DisplayManager.class).getDisplay( Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo); int dividerWindowWidth = ctx.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_thickness); int dividerInsets = ctx.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_divider_insets); return new DividerSnapAlgorithm(ctx.getResources(), displayInfo.logicalWidth, displayInfo.logicalHeight, dividerWindowWidth - 2 * dividerInsets, ctx.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT, insets); } public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, boolean isHorizontalDivision, Rect insets) { mMinFlingVelocityPxPerSecond = Loading @@ -85,6 +106,8 @@ public class DividerSnapAlgorithm { com.android.internal.R.integer.config_dockedStackDividerSnapMode); mFixedRatio = res.getFraction( com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1); mMinimalSizeResizableTask = res.getDimensionPixelSize( com.android.internal.R.dimen.default_minimal_size_resizable_task); calculateTargets(isHorizontalDivision); mFirstSplitTarget = mTargets.get(1); mLastSplitTarget = mTargets.get(mTargets.size() - 2); Loading @@ -93,6 +116,20 @@ public class DividerSnapAlgorithm { mMiddleTarget = mTargets.get(mTargets.size() / 2); } /** * @return whether it's feasible to enable split screen in the current configuration, i.e. when * snapping in the middle both tasks are larger than the minimal task size. */ public boolean isSplitScreenFeasible() { int statusBarSize = mInsets.top; int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right; int size = mIsHorizontalDivision ? mDisplayHeight : mDisplayWidth; int availableSpace = size - navBarSize - statusBarSize - mDividerSize; return availableSpace / 2 >= mMinimalSizeResizableTask; } public SnapTarget calculateSnapTarget(int position, float velocity) { return calculateSnapTarget(position, velocity, true /* hardDismiss */); } Loading Loading @@ -212,10 +249,10 @@ public class DividerSnapAlgorithm { mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f)); switch (mSnapMode) { case SNAP_MODE_16_9: addRatio16_9Targets(isHorizontalDivision); addRatio16_9Targets(isHorizontalDivision, dividerMax); break; case SNAP_FIXED_RATIO: addFixedDivisionTargets(isHorizontalDivision); addFixedDivisionTargets(isHorizontalDivision, dividerMax); break; case SNAP_ONLY_1_1: addMiddleTarget(isHorizontalDivision); Loading @@ -225,19 +262,24 @@ public class DividerSnapAlgorithm { mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f)); } private void addFixedDivisionTargets(boolean isHorizontalDivision) { private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition, int bottomPosition, int dividerMax) { maybeAddTarget(topPosition, topPosition - mInsets.top); addMiddleTarget(isHorizontalDivision); maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom - (bottomPosition + mDividerSize)); } private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) { int start = isHorizontalDivision ? mInsets.top : mInsets.left; int end = isHorizontalDivision ? mDisplayHeight - mInsets.bottom : mDisplayWidth - mInsets.right; mTargets.add(new SnapTarget((int) (start + mFixedRatio * (end - start)) - mDividerSize / 2, SnapTarget.FLAG_NONE)); addMiddleTarget(isHorizontalDivision); mTargets.add(new SnapTarget((int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2, SnapTarget.FLAG_NONE)); int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2; int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2; addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); } private void addRatio16_9Targets(boolean isHorizontalDivision) { private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) { int start = isHorizontalDivision ? mInsets.top : mInsets.left; int end = isHorizontalDivision ? mDisplayHeight - mInsets.bottom Loading @@ -248,9 +290,19 @@ public class DividerSnapAlgorithm { : mDisplayHeight - mInsets.bottom; float size = 9.0f / 16.0f * (endOther - startOther); int sizeInt = (int) Math.floor(size); mTargets.add(new SnapTarget(start + sizeInt, SnapTarget.FLAG_NONE)); addMiddleTarget(isHorizontalDivision); mTargets.add(new SnapTarget(end - sizeInt - mDividerSize, SnapTarget.FLAG_NONE)); int topPosition = start + sizeInt; int bottomPosition = end - sizeInt - mDividerSize; addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); } /** * Adds a target at {@param position} but only if the area with size of {@param smallerSize} * meets the minimal size requirement. */ private void maybeAddTarget(int position, int smallerSize) { if (smallerSize >= mMinimalSizeResizableTask) { mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE)); } } private void addMiddleTarget(boolean isHorizontalDivision) { Loading
core/res/res/values/config.xml +0 −4 Original line number Diff line number Diff line Loading @@ -2421,10 +2421,6 @@ disables NetworkPolicyManagerService's presentation of data-usage notifications. --> <string translatable="false" name="config_networkPolicyNotificationComponent"></string> <!-- The fraction of display size (lower of height and width) that will be used to determine the default minimal size for resizeable tasks. --> <fraction name="config_displayFractionForDefaultMinimalSizeOfResizeableTask">25%</fraction> <!-- The BT name of the keyboard packaged with the device. If this is defined, SystemUI will automatically try to pair with it when the device exits tablet mode. --> <string translatable="false" name="config_packagedKeyboardName"></string> Loading
core/res/res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -455,4 +455,7 @@ <item type="fraction" name="docked_stack_divider_fixed_ratio">34.15%</item> <dimen name="resize_shadow_size">5dp</dimen> <!-- The default minimal size of a resizable task, in both dimensions. --> <dimen name="default_minimal_size_resizable_task">220dp</dimen> </resources>
core/res/res/values/symbols.xml +1 −1 Original line number Diff line number Diff line Loading @@ -1726,7 +1726,7 @@ <java-symbol type="id" name="replace_app_icon" /> <java-symbol type="id" name="replace_message" /> <java-symbol type="fraction" name="config_dimBehindFadeDuration" /> <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" /> <java-symbol type="dimen" name="default_minimal_size_resizable_task" /> <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" /> <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" /> <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/> Loading
packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +19 −1 Original line number Diff line number Diff line Loading @@ -19,15 +19,20 @@ package com.android.systemui.recents.views; import android.app.ActivityManager; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.provider.Settings; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewDebug; import android.widget.Toast; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsImpl; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.ConfigurationChangedEvent; import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent; import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; Loading Loading @@ -81,12 +86,20 @@ public class RecentsViewTouchHandler { private float mDragSlop; private DropTarget mLastDropTarget; private DividerSnapAlgorithm mDividerSnapAlgorithm; private ArrayList<DropTarget> mDropTargets = new ArrayList<>(); private ArrayList<TaskStack.DockState> mVisibleDockStates = new ArrayList<>(); public RecentsViewTouchHandler(RecentsView rv) { mRv = rv; mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop(); updateSnapAlgorithm(); } private void updateSnapAlgorithm() { Rect insets = new Rect(); SystemServicesProxy.getInstance(mRv.getContext()).getStableInsets(insets); mDividerSnapAlgorithm = DividerSnapAlgorithm.create(mRv.getContext(), insets); } /** Loading Loading @@ -150,7 +163,8 @@ public class RecentsViewTouchHandler { mTaskView.setTranslationY(y); mVisibleDockStates.clear(); if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) { if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask() && mDividerSnapAlgorithm.isSplitScreenFeasible()) { if (!event.task.isDockable) { Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message, Toast.LENGTH_SHORT).show(); Loading @@ -176,6 +190,10 @@ public class RecentsViewTouchHandler { mLastDropTarget = null; } public final void onBusEvent(ConfigurationChangedEvent event) { updateSnapAlgorithm(); } /** * Handles dragging touch events */ Loading