/**
* Docks the top-most task and opens recents.
*/
- void dockTopTask();
+ void dockTopTask(boolean draggingInRecents);
+
+ /**
+ * Called during a drag-from-navbar-in gesture.
+ *
+ * @param distanceFromTop the distance of the current drag in gesture from the top of the
+ * screen
+ */
+ void onDraggingInRecents(float distanceFromTop);
+
+ /**
+ * Called when the gesture to drag in recents ended.
+ *
+ * @param velocity the velocity of the finger when releasing it in pixels per second
+ */
+ void onDraggingInRecentsEnded(float velocity);
}
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recents.Recents.class,
com.android.systemui.volume.VolumeUI.class,
+ Divider.class,
com.android.systemui.statusbar.SystemBars.class,
com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.keyboard.KeyboardUI.class,
- Divider.class
};
/**
oneway interface IRecentsNonSystemUserCallbacks {
void preloadRecents();
void cancelPreloadingRecents();
- void showRecents(boolean triggeredFromAltTab);
+ void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents);
void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecents();
void onConfigurationChanged();
+ void onDraggingInRecents(float distanceFromTop);
+ void onDraggingInRecentsEnded(float velocity);
}
private Handler mHandler;
private RecentsImpl mImpl;
+ private int mDraggingInRecentsCurrentUser;
// Only For system user, this is the callbacks instance we return to each secondary user
private RecentsSystemUser mSystemUserCallbacks;
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.showRecents(triggeredFromAltTab);
+ mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */);
} else {
if (mSystemUserCallbacks != null) {
IRecentsNonSystemUserCallbacks callbacks =
mSystemUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
if (callbacks != null) {
try {
- callbacks.showRecents(triggeredFromAltTab);
+ callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */);
} catch (RemoteException e) {
Log.e(TAG, "Callback failed", e);
}
}
@Override
- public void dockTopTask() {
- mImpl.dockTopTask();
+ public void dockTopTask(boolean draggingInRecents) {
+ mImpl.dockTopTask(draggingInRecents);
+ if (draggingInRecents) {
+ mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser();
+ }
+ }
+
+ @Override
+ public void onDraggingInRecents(float distanceFromTop) {
+ if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
+ mImpl.onDraggingInRecents(distanceFromTop);
+ } else {
+ if (mSystemUserCallbacks != null) {
+ IRecentsNonSystemUserCallbacks callbacks =
+ mSystemUserCallbacks.getNonSystemUserRecentsForUser(
+ mDraggingInRecentsCurrentUser);
+ if (callbacks != null) {
+ try {
+ callbacks.onDraggingInRecents(distanceFromTop);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Callback failed", e);
+ }
+ } else {
+ Log.e(TAG, "No SystemUI callbacks found for user: "
+ + mDraggingInRecentsCurrentUser);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onDraggingInRecentsEnded(float velocity) {
+ if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
+ mImpl.onDraggingInRecentsEnded(velocity);
+ } else {
+ if (mSystemUserCallbacks != null) {
+ IRecentsNonSystemUserCallbacks callbacks =
+ mSystemUserCallbacks.getNonSystemUserRecentsForUser(
+ mDraggingInRecentsCurrentUser);
+ if (callbacks != null) {
+ try {
+ callbacks.onDraggingInRecentsEnded(velocity);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Callback failed", e);
+ }
+ } else {
+ Log.e(TAG, "No SystemUI callbacks found for user: "
+ + mDraggingInRecentsCurrentUser);
+ }
+ }
+ }
}
@Override
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
+import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
+import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
RecentsAppWidgetHost mAppWidgetHost;
boolean mBootCompleted;
boolean mCanReuseTaskStackViews = true;
+ boolean mDraggingInRecents;
// Task launching
Rect mSearchBarBounds = new Rect();
public void run() {
// When this fires, then the user has not released alt-tab for at least
// FAST_ALT_TAB_DELAY_MS milliseconds
- showRecents(mTriggeredFromAltTab);
+ showRecents(mTriggeredFromAltTab, false /* draggingInRecents */);
}
});
Bitmap mThumbnailTransitionBitmapCache;
Task mThumbnailTransitionBitmapCacheKey;
-
public RecentsImpl(Context context) {
mContext = context;
mHandler = new Handler();
}
@Override
- public void showRecents(boolean triggeredFromAltTab) {
+ public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents) {
mTriggeredFromAltTab = triggeredFromAltTab;
+ mDraggingInRecents = draggingInRecents;
if (mFastAltTabTrigger.hasTriggered()) {
// We are calling this from the doze trigger, so just fall through to show Recents
mFastAltTabTrigger.resetTrigger();
return;
}
+ mDraggingInRecents = false;
mTriggeredFromAltTab = false;
try {
// Do nothing
}
+ @Override
+ public void onDraggingInRecents(float distanceFromTop) {
+ EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEvent(distanceFromTop));
+ }
+
+ @Override
+ public void onDraggingInRecentsEnded(float velocity) {
+ EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEndedEvent(velocity));
+ }
+
/**
* Transitions to the next recent task in the stack.
*/
showRelativeAffiliatedTask(false);
}
- public void dockTopTask() {
+ public void dockTopTask(boolean draggingInRecents) {
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
ssp.startTaskInDockedMode(topTask.id,
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
- showRecents(false /* triggeredFromAltTab */);
+ showRecents(false /* triggeredFromAltTab */, draggingInRecents);
}
}
launchState.launchedNumVisibleTasks = vr.numVisibleTasks;
launchState.launchedNumVisibleThumbnails = vr.numVisibleThumbnails;
launchState.launchedHasConfigurationChanged = false;
- launchState.startHidden = topTask != null && topTask.stackId == FREEFORM_WORKSPACE_STACK_ID;
+ launchState.startHidden = topTask != null && topTask.stackId == FREEFORM_WORKSPACE_STACK_ID
+ || mDraggingInRecents;
Intent intent = new Intent();
intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
queueEvent(event);
}
+ /**
+ * If this method is called from the main thread, it will be handled directly. If this method
+ * is not called from the main thread, it will be posted onto the main thread.
+ */
+ public void sendOntoMainThread(Event event) {
+ long callingThreadId = Thread.currentThread().getId();
+ if (callingThreadId != mHandler.getLooper().getThread().getId()) {
+ post(event);
+ } else {
+ send(event);
+ }
+ }
+
/** Prevent post()ing an InterprocessEvent */
@Deprecated
public void post(InterprocessEvent event) {
--- /dev/null
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus.Event;
+
+/**
+ * This event is sent when the user finished dragging in recents.
+ */
+public class DraggingInRecentsEndedEvent extends Event {
+
+ public final float velocity;
+
+ public DraggingInRecentsEndedEvent(float velocity) {
+ this.velocity = velocity;
+ }
+}
--- /dev/null
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus.Event;
+
+/**
+ * This event is sent when the user changed how far they are dragging in recents.
+ */
+public class DraggingInRecentsEvent extends Event {
+
+ public final float distanceFromTop;
+
+ public DraggingInRecentsEvent(float distanceFromTop) {
+ this.distanceFromTop = distanceFromTop;
+ }
+}
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
+import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
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;
}
}
+ public final void onBusEvent(DraggingInRecentsEvent event) {
+ setStackViewVisibility(View.VISIBLE);
+ setTranslationY(event.distanceFromTop - mTaskStackView.getTaskViews().get(0).getY());
+ }
+
+ public final void onBusEvent(DraggingInRecentsEndedEvent event) {
+ animate().translationY(0f);
+ }
+
/**
* Updates the dock region to match the specified dock state.
*/
private static final String TAG = "Divider";
private int mDividerWindowWidth;
private DividerWindowManager mWindowManager;
+ private DividerView mView;
@Override
public void start() {
mDividerWindowWidth = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
update(mContext.getResources().getConfiguration());
+ putComponent(Divider.class, this);
}
@Override
update(newConfig);
}
+ public DividerView getView() {
+ return mView;
+ }
+
private void addDivider(Configuration configuration) {
- DividerView view = (DividerView)
+ mView = (DividerView)
LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
final int width = landscape ? mDividerWindowWidth : MATCH_PARENT;
final int height = landscape ? MATCH_PARENT : mDividerWindowWidth;
- mWindowManager.add(view, width, height);
- view.setWindowManager(mWindowManager);
+ mWindowManager.add(mView, width, height);
+ mView.setWindowManager(mWindowManager);
}
private void removeDivider() {
// TODO: Better calculation
targets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START));
- targets.add(new SnapTarget((int) (0.35f * dividerMax) - mDividerSize / 2,
+ targets.add(new SnapTarget((int) (0.38f * dividerMax) - mDividerSize / 2,
SnapTarget.FLAG_NONE));
targets.add(new SnapTarget(dividerMax / 2 - mDividerSize / 2, SnapTarget.FLAG_NONE));
- targets.add(new SnapTarget((int) (0.65f * dividerMax) - mDividerSize / 2,
+ targets.add(new SnapTarget((int) (0.62f * dividerMax) - mDividerSize / 2,
SnapTarget.FLAG_NONE));
targets.add(new SnapTarget(dividerMax, SnapTarget.FLAG_DISMISS_END));
return targets;
mWindowManager = windowManager;
}
+ public WindowManagerProxy getWindowManagerProxy() {
+ return mWindowManagerProxy;
+ }
+
+ public boolean startDragging() {
+ mDockSide = mWindowManagerProxy.getDockSide();
+ if (mDockSide != WindowManager.DOCKED_INVALID) {
+ mWindowManagerProxy.setResizing(true);
+ mWindowManager.setSlippery(false);
+ liftBackground();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void stopDragging(int position, float velocity) {
+ fling(position, velocity);
+ mWindowManager.setSlippery(true);
+ releaseBackground();
+ }
+
@Override
public boolean onTouch(View v, MotionEvent event) {
convertToScreenCoordinates(event);
mStartX = (int) event.getX();
mStartY = (int) event.getY();
getLocationOnScreen(mTempInt2);
- mDockSide = mWindowManagerProxy.getDockSide();
+ boolean result = startDragging();
if (isHorizontalDivision()) {
mStartPosition = mTempInt2[1] + mDividerInsets;
} else {
mStartPosition = mTempInt2[0] + mDividerInsets;
}
- if (mDockSide != WindowManager.DOCKED_INVALID) {
- mWindowManagerProxy.setResizing(true);
- mWindowManager.setSlippery(false);
- liftBackground();
- return true;
- } else {
- return false;
- }
+ return result;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
int x = (int) event.getX();
y = (int) event.getRawY();
mVelocityTracker.computeCurrentVelocity(1000);
- fling(x, y, mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
-
- mWindowManager.setSlippery(true);
- releaseBackground();
+ int position = calculatePosition(x, y);
+ stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
+ : mVelocityTracker.getXVelocity());
break;
}
return true;
event.setLocation(event.getRawX(), event.getRawY());
}
- private void fling(int x, int y, float xVelocity, float yVelocity) {
- int position = calculatePosition(x, y);
- float velocity = isHorizontalDivision() ? yVelocity : xVelocity;
+ private void fling(int position, float velocity) {
final SnapTarget snapTarget = new DividerSnapAlgorithm(getContext(), mFlingAnimationUtils,
mDividerSize, isHorizontalDivision()).calculateSnapTarget(position, velocity);
return isHorizontalDivision() ? calculateYPosition(touchY) : calculateXPosition(touchX);
}
- private boolean isHorizontalDivision() {
- return mDockSide == WindowManager.DOCKED_TOP
- || mDockSide == WindowManager.DOCKED_BOTTOM;
+ public boolean isHorizontalDivision() {
+ return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
}
private int calculateXPosition(int touchX) {
return mStartPosition + touchY - mStartY;
}
- private void resizeStack(int position) {
+ public void resizeStack(int position) {
mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
switch (mDockSide) {
case WindowManager.DOCKED_LEFT:
--- /dev/null
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.SystemProperties;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.BaseStatusBar;
+
+import static android.view.WindowManager.*;
+
+/**
+ * Class to detect gestures on the navigation bar.
+ */
+public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener {
+
+ private static final String DOCK_WINDOW_GESTURE_ENABLED_PROP = "persist.dock_gesture_enabled";
+
+ /**
+ * When dragging from the navigation bar, we drag in recents.
+ */
+ private static final int DRAG_MODE_RECENTS = 0;
+
+ /**
+ * When dragging from the navigation bar, we drag the divider.
+ */
+ private static final int DRAG_MODE_DIVIDER = 1;
+
+ private RecentsComponent mRecentsComponent;
+ private Divider mDivider;
+ private boolean mIsVertical;
+ private boolean mIsRTL;
+
+ private final GestureDetector mTaskSwitcherDetector;
+ private final int mScrollTouchSlop;
+ private final int mTouchSlop;
+ private final int mMinFlingVelocity;
+ private int mTouchDownX;
+ private int mTouchDownY;
+ private VelocityTracker mVelocityTracker;
+
+ private boolean mDockWindowEnabled;
+ private boolean mDockWindowTouchSlopExceeded;
+ private int mDragMode;
+
+ public NavigationBarGestureHelper(Context context) {
+ ViewConfiguration configuration = ViewConfiguration.get(context);
+ Resources r = context.getResources();
+ mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
+ mTaskSwitcherDetector = new GestureDetector(context, this);
+ mDockWindowEnabled = SystemProperties.getBoolean(DOCK_WINDOW_GESTURE_ENABLED_PROP, false);
+ }
+
+ public void setComponents(RecentsComponent recentsComponent, Divider divider) {
+ mRecentsComponent = recentsComponent;
+ mDivider = divider;
+ }
+
+ public void setBarState(boolean isVertical, boolean isRTL) {
+ mIsVertical = isVertical;
+ mIsRTL = isRTL;
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ // If we move more than a fixed amount, then start capturing for the
+ // task switcher detector
+ mTaskSwitcherDetector.onTouchEvent(event);
+ int action = event.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ mTouchDownX = (int) event.getX();
+ mTouchDownY = (int) event.getY();
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ int xDiff = Math.abs(x - mTouchDownX);
+ int yDiff = Math.abs(y - mTouchDownY);
+ boolean exceededTouchSlop = !mIsVertical
+ ? xDiff > mScrollTouchSlop && xDiff > yDiff
+ : yDiff > mScrollTouchSlop && yDiff > xDiff;
+ if (exceededTouchSlop) {
+ return true;
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ break;
+ }
+ return mDockWindowEnabled && interceptDockWindowEvent(event);
+ }
+
+ private boolean interceptDockWindowEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ handleDragActionDownEvent(event);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ return handleDragActionMoveEvent(event);
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ handleDragActionUpEvent(event);
+ break;
+ }
+ return false;
+ }
+
+ private boolean handleDockWindowEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ handleDragActionDownEvent(event);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ handleDragActionMoveEvent(event);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ handleDragActionUpEvent(event);
+ break;
+ }
+ return true;
+ }
+
+ private void handleDragActionDownEvent(MotionEvent event) {
+ mVelocityTracker = VelocityTracker.obtain();
+ mVelocityTracker.addMovement(event);
+ mDockWindowTouchSlopExceeded = false;
+ mTouchDownX = (int) event.getX();
+ mTouchDownY = (int) event.getY();
+ }
+
+ private boolean handleDragActionMoveEvent(MotionEvent event) {
+ mVelocityTracker.addMovement(event);
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ int xDiff = Math.abs(x - mTouchDownX);
+ int yDiff = Math.abs(y - mTouchDownY);
+ if (!mDockWindowTouchSlopExceeded) {
+ boolean touchSlopExceeded = !mIsVertical
+ ? yDiff > mTouchSlop && yDiff > xDiff
+ : xDiff > mTouchSlop && xDiff > yDiff;
+ if (touchSlopExceeded && mDivider.getView().getWindowManagerProxy().getDockSide()
+ == DOCKED_INVALID) {
+ mDragMode = calculateDragMode();
+ mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS);
+ if (mDragMode == DRAG_MODE_DIVIDER) {
+ mDivider.getView().startDragging();
+ }
+ mDockWindowTouchSlopExceeded = true;
+ return true;
+ }
+ } else {
+ if (mDragMode == DRAG_MODE_DIVIDER) {
+ mDivider.getView().resizeStack(
+ !mIsVertical ? (int) event.getRawY() : (int) event.getRawX());
+ } else if (mDragMode == DRAG_MODE_RECENTS) {
+ mRecentsComponent.onDraggingInRecents(event.getRawY());
+ }
+ }
+ return false;
+ }
+
+ private void handleDragActionUpEvent(MotionEvent event) {
+ mVelocityTracker.addMovement(event);
+ mVelocityTracker.computeCurrentVelocity(1000);
+ if (mDockWindowTouchSlopExceeded) {
+ if (mDragMode == DRAG_MODE_DIVIDER) {
+ mDivider.getView().stopDragging(!mIsVertical
+ ? (int) event.getRawY()
+ : (int) event.getRawX(),
+ !mIsVertical
+ ? mVelocityTracker.getXVelocity()
+ : mVelocityTracker.getYVelocity());
+ } else if (mDragMode == DRAG_MODE_RECENTS) {
+ mRecentsComponent.onDraggingInRecentsEnded(mVelocityTracker.getYVelocity());
+ }
+ }
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ private int calculateDragMode() {
+ if (mIsVertical && !mDivider.getView().isHorizontalDivision()) {
+ return DRAG_MODE_DIVIDER;
+ }
+ if (!mIsVertical && mDivider.getView().isHorizontalDivision()) {
+ return DRAG_MODE_DIVIDER;
+ }
+ return DRAG_MODE_RECENTS;
+ }
+
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean result = mTaskSwitcherDetector.onTouchEvent(event);
+ if (mDockWindowEnabled) {
+ result |= handleDockWindowEvent(event);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ float absVelX = Math.abs(velocityX);
+ float absVelY = Math.abs(velocityY);
+ boolean isValidFling = absVelX > mMinFlingVelocity &&
+ mIsVertical ? (absVelY > absVelX) : (absVelX > absVelY);
+ if (isValidFling) {
+ boolean showNext;
+ if (!mIsRTL) {
+ showNext = mIsVertical ? (velocityY < 0) : (velocityX < 0);
+ } else {
+ // In RTL, vertical is still the same, but horizontal is flipped
+ showNext = mIsVertical ? (velocityY < 0) : (velocityX > 0);
+ }
+ if (showNext) {
+ mRecentsComponent.showNextAffiliatedTask();
+ } else {
+ mRecentsComponent.showPrevAffiliatedTask();
+ }
+ }
+ return true;
+ }
+}
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonView;
private Drawable mRecentIcon;
private Drawable mRecentLandIcon;
- private NavigationBarViewTaskSwitchHelper mTaskSwitchHelper;
+ private NavigationBarGestureHelper mGestureHelper;
private DeadZone mDeadZone;
private final NavigationBarTransitions mBarTransitions;
mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
mVertical = false;
mShowMenu = false;
- mTaskSwitchHelper = new NavigationBarViewTaskSwitchHelper(context);
+ mGestureHelper = new NavigationBarGestureHelper(context);
getIcons(res);
return mBarTransitions;
}
- public void setBar(PhoneStatusBar phoneStatusBar) {
- mTaskSwitchHelper.setBar(phoneStatusBar);
+ public void setComponents(RecentsComponent recentsComponent, Divider divider) {
+ mGestureHelper.setComponents(recentsComponent, divider);
}
public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mTaskSwitchHelper.onTouchEvent(event)) {
+ if (mGestureHelper.onTouchEvent(event)) {
return true;
}
if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTaskSwitchHelper.onInterceptTouchEvent(event);
+ return mGestureHelper.onInterceptTouchEvent(event);
}
public void abortCurrentGesture() {
private void updateTaskSwitchHelper() {
boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- mTaskSwitchHelper.setBarState(mVertical, isRtl);
+ mGestureHelper.setBarState(mVertical, isRtl);
}
@Override
+++ /dev/null
-/*
- * Copyright (C) 2014 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.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.BaseStatusBar;
-
-public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnGestureListener {
-
- private BaseStatusBar mBar;
- private boolean mIsVertical;
- private boolean mIsRTL;
-
- private final GestureDetector mTaskSwitcherDetector;
- private final int mScrollTouchSlop;
- private final int mMinFlingVelocity;
- private int mTouchDownX;
- private int mTouchDownY;
-
- public NavigationBarViewTaskSwitchHelper(Context context) {
- ViewConfiguration configuration = ViewConfiguration.get(context);
- Resources r = context.getResources();
- mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
- mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
- mTaskSwitcherDetector = new GestureDetector(context, this);
- }
-
- public void setBar(BaseStatusBar phoneStatusBar) {
- mBar = phoneStatusBar;
- }
-
- public void setBarState(boolean isVertical, boolean isRTL) {
- mIsVertical = isVertical;
- mIsRTL = isRTL;
- }
-
- public boolean onInterceptTouchEvent(MotionEvent event) {
- // If we move more than a fixed amount, then start capturing for the
- // task switcher detector
- mTaskSwitcherDetector.onTouchEvent(event);
- int action = event.getAction();
- boolean intercepted = false;
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- mTouchDownX = (int) event.getX();
- mTouchDownY = (int) event.getY();
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- int x = (int) event.getX();
- int y = (int) event.getY();
- int xDiff = Math.abs(x - mTouchDownX);
- int yDiff = Math.abs(y - mTouchDownY);
- boolean exceededTouchSlop = !mIsVertical
- ? xDiff > mScrollTouchSlop && xDiff > yDiff
- : yDiff > mScrollTouchSlop && yDiff > xDiff;
- if (exceededTouchSlop) {
- return true;
- }
- break;
- }
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- break;
- }
- return intercepted;
- }
-
- public boolean onTouchEvent(MotionEvent event) {
- return mTaskSwitcherDetector.onTouchEvent(event);
- }
-
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- float absVelX = Math.abs(velocityX);
- float absVelY = Math.abs(velocityY);
- boolean isValidFling = absVelX > mMinFlingVelocity &&
- mIsVertical ? (absVelY > absVelX) : (absVelX > absVelY);
- if (isValidFling) {
- boolean showNext;
- if (!mIsRTL) {
- showNext = mIsVertical ? (velocityY < 0) : (velocityX < 0);
- } else {
- // In RTL, vertical is still the same, but horizontal is flipped
- showNext = mIsVertical ? (velocityY < 0) : (velocityX > 0);
- }
- if (showNext) {
- mBar.showNextAffiliatedTask();
- } else {
- mBar.showPreviousAffiliatedTask();
- }
- }
- return true;
- }
-}
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.BaseStatusBar;
context, R.layout.navigation_bar, null);
}
mNavigationBarView.setDisabledFlags(mDisabled1);
- mNavigationBarView.setBar(this);
+ mNavigationBarView.setComponents(mRecents, getComponent(Divider.class));
mNavigationBarView.setOnVerticalChangedListener(
new NavigationBarView.OnVerticalChangedListener() {
@Override
@Override
public boolean onLongClick(View v) {
if (mRecents != null) {
- mRecents.dockTopTask();
+ mRecents.dockTopTask(false /* draggingInRecents */);
return true;
}
return false;