diff options
Diffstat (limited to 'src/com/android/launcher3/Launcher.java')
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 279 |
1 files changed, 105 insertions, 174 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index c73a7a61d..30d5b17c5 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -30,7 +30,6 @@ import android.app.AlertDialog; import android.app.SearchManager; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; @@ -56,7 +55,6 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; import android.os.Trace; @@ -69,6 +67,8 @@ import android.util.Log; import android.view.Display; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; +import android.view.KeyboardShortcutGroup; +import android.view.KeyboardShortcutInfo; import android.view.Menu; import android.view.MotionEvent; import android.view.Surface; @@ -79,9 +79,9 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; import android.view.inputmethod.InputMethodManager; -import android.widget.Advanceable; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; @@ -106,6 +106,7 @@ import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dynamicui.ExtractedColors; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.keyboard.CustomActionsPopup; import com.android.launcher3.keyboard.ViewGroupFocusHelper; import com.android.launcher3.logging.FileLog; import com.android.launcher3.logging.UserEventDispatcher; @@ -254,7 +255,6 @@ public class Launcher extends Activity @Thunk WidgetsContainerView mWidgetsView; @Thunk WidgetsModel mWidgetsModel; - private Bundle mSavedState; // We set the state in both onCreate and then onNewIntent in some cases, which causes both // scroll issues (because the workspace may not have been measured yet) and extra work. // Instead, just save the state that we need to restore Launcher to, and commit it in onResume. @@ -275,27 +275,16 @@ public class Launcher extends Activity private IconCache mIconCache; private ExtractedColors mExtractedColors; private LauncherAccessibilityDelegate mAccessibilityDelegate; + private Handler mHandler = new Handler(); private boolean mIsResumeFromActionScreenOff; - @Thunk boolean mUserPresent = true; - private boolean mVisible; - private boolean mHasFocus; - private boolean mAttached; + private boolean mHasFocus = false; + private boolean mAttached = false; /** Maps launcher activity components to their list of shortcut ids. */ private MultiHashMap<ComponentKey, String> mDeepShortcutMap = new MultiHashMap<>(); private View.OnTouchListener mHapticFeedbackTouchListener; - // Related to the auto-advancing of widgets - private final int ADVANCE_MSG = 1; - private static final int ADVANCE_INTERVAL = 20000; - private static final int ADVANCE_STAGGER = 250; - - private boolean mAutoAdvanceRunning = false; - private long mAutoAdvanceSentTime; - private long mAutoAdvanceTimeLeft = -1; - @Thunk HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance = new HashMap<>(); - // Determines how long to wait after a rotation before restoring the screen orientation to // match the sensor state. private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500; @@ -354,6 +343,9 @@ public class Launcher extends Activity private UserEventDispatcher mUserEventDispatcher; + private float mLastDispatchTouchEventX = 0.0f; + private float mEdgeOfScreenThresholdPx = 0.0f; + public ViewGroupFocusHelper mFocusHandler; private boolean mRotationEnabled = false; @@ -424,6 +416,9 @@ public class Launcher extends Activity setContentView(R.layout.launcher); + mEdgeOfScreenThresholdPx = getResources() + .getDimensionPixelSize(R.dimen.edge_of_screen_threshold); + setupViews(); mDeviceProfile.layout(this, false /* notifyListeners */); mExtractedColors = new ExtractedColors(); @@ -434,8 +429,7 @@ public class Launcher extends Activity lockAllApps(); - mSavedState = savedInstanceState; - restoreState(mSavedState); + restoreState(savedInstanceState); if (LauncherAppState.PROFILE_STARTUP) { Trace.endSection(); @@ -443,11 +437,18 @@ public class Launcher extends Activity // We only load the page synchronously if the user rotates (or triggers a // configuration change) while launcher is in the foreground - if (!mModel.startLoader(mWorkspace.getRestorePage())) { + int currentScreen = PagedView.INVALID_RESTORE_PAGE; + if (savedInstanceState != null) { + currentScreen = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, currentScreen); + } + if (!mModel.startLoader(currentScreen)) { // If we are not binding synchronously, show a fade in animation when // the first page bind completes. mDragLayer.setAlpha(0); } else { + // Pages bound synchronously. + mWorkspace.setCurrentPage(currentScreen); + setWorkspaceLoading(true); } @@ -611,7 +612,7 @@ public class Launcher extends Activity } /** - * Invoked by subclasses to signal a change to the {@link #addCustomContentToLeft} value to + * Invoked by subclasses to signal a change to the {@link #addToCustomContentPage} value to * ensure the custom content page is added or removed if necessary. */ protected void invalidateHasCustomContentToLeft() { @@ -1263,22 +1264,6 @@ public class Launcher extends Activity } /** - * Given the integer (ordinal) value of a State enum instance, convert it to a variable of type - * State - */ - private static State intToState(int stateOrdinal) { - State state = State.WORKSPACE; - final State[] stateValues = State.values(); - for (int i = 0; i < stateValues.length; i++) { - if (stateValues[i].ordinal() == stateOrdinal) { - state = stateValues[i]; - break; - } - } - return state; - } - - /** * Restores the previous state, if it exists. * * @param savedState The previous state. @@ -1288,17 +1273,14 @@ public class Launcher extends Activity return; } - State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal())); + int stateOrdinal = savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()); + State[] stateValues = State.values(); + State state = (stateOrdinal >= 0 && stateOrdinal < stateValues.length) + ? stateValues[stateOrdinal] : State.WORKSPACE; if (state == State.APPS || state == State.WIDGETS) { mOnResumeState = state; } - int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, - PagedView.INVALID_RESTORE_PAGE); - if (currentScreen != PagedView.INVALID_RESTORE_PAGE) { - mWorkspace.setRestorePage(currentScreen); - } - PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS); if (requestArgs != null) { setWaitingForResult(requestArgs); @@ -1576,10 +1558,6 @@ public class Launcher extends Activity mWorkspace.addInScreen(hostView, item.container, item.screenId, item.cellX, item.cellY, item.spanX, item.spanY, insert); - - if (!item.isCustomWidget()) { - addWidgetToAutoAdvanceIfNeeded(hostView, appWidgetInfo); - } } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -1587,9 +1565,7 @@ public class Launcher extends Activity public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (Intent.ACTION_SCREEN_OFF.equals(action)) { - mUserPresent = false; - mDragLayer.clearAllResizeFrames(); - updateAutoAdvanceState(); + mDragLayer.clearResizeFrame(); // Reset AllApps to its initial state only if we are not in the middle of // processing a multi-step drop @@ -1600,9 +1576,6 @@ public class Launcher extends Activity } } mIsResumeFromActionScreenOff = true; - } else if (Intent.ACTION_USER_PRESENT.equals(action)) { - mUserPresent = true; - updateAutoAdvanceState(); } } }; @@ -1614,11 +1587,9 @@ public class Launcher extends Activity // Listen for broadcasts related to user-presence final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(Intent.ACTION_USER_PRESENT); registerReceiver(mReceiver, filter); FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView()); mAttached = true; - mVisible = true; if (mLauncherCallbacks != null) { mLauncherCallbacks.onAttachedToWindow(); @@ -1628,13 +1599,10 @@ public class Launcher extends Activity @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); - mVisible = false; - if (mAttached) { unregisterReceiver(mReceiver); mAttached = false; } - updateAutoAdvanceState(); if (mLauncherCallbacks != null) { mLauncherCallbacks.onDetachedFromWindow(); @@ -1642,12 +1610,10 @@ public class Launcher extends Activity } public void onWindowVisibilityChanged(int visibility) { - mVisible = visibility == View.VISIBLE; - updateAutoAdvanceState(); // The following code used to be in onResume, but it turns out onResume is called when // you're in All Apps and click home to go to the workspace. onWindowVisibilityChanged // is a more appropriate event to handle - if (mVisible) { + if (visibility == View.VISIBLE) { if (!mWorkspaceLoading) { final ViewTreeObserver observer = mWorkspace.getViewTreeObserver(); // We want to let Launcher draw itself at least once before we force it to build @@ -1682,72 +1648,6 @@ public class Launcher extends Activity } } - @Thunk void sendAdvanceMessage(long delay) { - mHandler.removeMessages(ADVANCE_MSG); - Message msg = mHandler.obtainMessage(ADVANCE_MSG); - mHandler.sendMessageDelayed(msg, delay); - mAutoAdvanceSentTime = System.currentTimeMillis(); - } - - @Thunk void updateAutoAdvanceState() { - boolean autoAdvanceRunning = mVisible && mUserPresent && !mWidgetsToAdvance.isEmpty(); - if (autoAdvanceRunning != mAutoAdvanceRunning) { - mAutoAdvanceRunning = autoAdvanceRunning; - if (autoAdvanceRunning) { - long delay = mAutoAdvanceTimeLeft == -1 ? ADVANCE_INTERVAL : mAutoAdvanceTimeLeft; - sendAdvanceMessage(delay); - } else { - if (!mWidgetsToAdvance.isEmpty()) { - mAutoAdvanceTimeLeft = Math.max(0, ADVANCE_INTERVAL - - (System.currentTimeMillis() - mAutoAdvanceSentTime)); - } - mHandler.removeMessages(ADVANCE_MSG); - mHandler.removeMessages(0); // Remove messages sent using postDelayed() - } - } - } - - @Thunk final Handler mHandler = new Handler(new Handler.Callback() { - - @Override - public boolean handleMessage(Message msg) { - if (msg.what == ADVANCE_MSG) { - int i = 0; - for (View key: mWidgetsToAdvance.keySet()) { - final View v = key.findViewById(mWidgetsToAdvance.get(key).autoAdvanceViewId); - final int delay = ADVANCE_STAGGER * i; - if (v instanceof Advanceable) { - mHandler.postDelayed(new Runnable() { - public void run() { - ((Advanceable) v).advance(); - } - }, delay); - } - i++; - } - sendAdvanceMessage(ADVANCE_INTERVAL); - } - return true; - } - }); - - private void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) { - if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return; - View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId); - if (v instanceof Advanceable) { - mWidgetsToAdvance.put(hostView, appWidgetInfo); - ((Advanceable) v).fyiWillBeAdvancedByHostKThx(); - updateAutoAdvanceState(); - } - } - - private void removeWidgetToAutoAdvance(View hostView) { - if (mWidgetsToAdvance.containsKey(hostView)) { - mWidgetsToAdvance.remove(hostView); - updateAutoAdvanceState(); - } - } - public void showOutOfSpaceMessage(boolean isHotseatLayout) { int strId = (isHotseatLayout ? R.string.hotseat_out_of_space : R.string.out_of_space); Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show(); @@ -1942,9 +1842,6 @@ public class Launcher extends Activity public void onDestroy() { super.onDestroy(); - // Remove all pending runnables - mHandler.removeMessages(ADVANCE_MSG); - mHandler.removeMessages(0); mWorkspace.removeCallbacks(mBuildLayersRunnable); mWorkspace.removeFolderListeners(); @@ -1967,8 +1864,6 @@ public class Launcher extends Activity } mAppWidgetHost = null; - mWidgetsToAdvance.clear(); - TextKeyListener.getInstance().release(); ((AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE)) @@ -2288,7 +2183,6 @@ public class Launcher extends Activity } else if (itemInfo instanceof LauncherAppWidgetInfo) { final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo; mWorkspace.removeWorkspaceItem(v); - removeWidgetToAutoAdvance(v); if (deleteFromDb) { deleteWidgetInfo(widgetInfo); } @@ -2781,6 +2675,7 @@ public class Launcher extends Activity } } + @TargetApi(Build.VERSION_CODES.M) private Bundle getActivityLaunchOptions(View v) { if (Utilities.ATLEAST_MARSHMALLOW) { int left = 0, top = 0; @@ -3081,6 +2976,12 @@ public class Launcher extends Activity } @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + mLastDispatchTouchEventX = ev.getX(); + return super.dispatchTouchEvent(ev); + } + + @Override public boolean onLongClick(View v) { if (!isDraggingEnabled()) return false; if (isWorkspaceLocked()) return false; @@ -3092,9 +2993,12 @@ public class Launcher extends Activity return true; } + boolean fromEdgeOfScreen = mLastDispatchTouchEventX < mEdgeOfScreenThresholdPx + || mLastDispatchTouchEventX > (mDeviceProfile.widthPx - mEdgeOfScreenThresholdPx); + if (v instanceof Workspace) { if (!mWorkspace.isInOverviewMode()) { - if (!mWorkspace.isTouchActive()) { + if (!mWorkspace.isTouchActive() && !fromEdgeOfScreen) { showOverviewMode(true); mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); @@ -3121,13 +3025,16 @@ public class Launcher extends Activity if (!mDragController.isDragging()) { if (itemUnderLongClick == null) { // User long pressed on empty space - mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); if (mWorkspace.isInOverviewMode()) { mWorkspace.startReordering(v); } else { + if (fromEdgeOfScreen) { + return false; + } showOverviewMode(true); } + mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } else { final boolean isAllAppsButton = !FeatureFlags.NO_ALL_APPS_ICON && isHotseatLayout(v) && @@ -3135,17 +3042,7 @@ public class Launcher extends Activity longClickCellInfo.cellX, longClickCellInfo.cellY)); if (!(itemUnderLongClick instanceof Folder || isAllAppsButton)) { // User long pressed on an item - DragOptions dragOptions = new DragOptions(); - if (itemUnderLongClick instanceof BubbleTextView) { - BubbleTextView icon = (BubbleTextView) itemUnderLongClick; - if (icon.hasDeepShortcuts()) { - DeepShortcutsContainer dsc = DeepShortcutsContainer.showForIcon(icon); - if (dsc != null) { - dragOptions.deferDragCondition = dsc.createDeferDragCondition(null); - } - } - } - mWorkspace.startDrag(longClickCellInfo, dragOptions); + mWorkspace.startDrag(longClickCellInfo, new DragOptions()); } } } @@ -3224,10 +3121,6 @@ public class Launcher extends Activity // Change the state *after* we've called all the transition code mState = State.WORKSPACE; - // Resume the auto-advance of widgets - mUserPresent = true; - updateAutoAdvanceState(); - if (changed) { // Send an accessibility event to announce the context change getWindow().getDecorView() @@ -3333,9 +3226,6 @@ public class Launcher extends Activity // Change the state *after* we've called all the transition code mState = toState; - // Pause the auto-advance of widgets until we are out of AllApps - mUserPresent = false; - updateAutoAdvanceState(); closeFolder(); closeShortcutsContainer(); @@ -3561,7 +3451,6 @@ public class Launcher extends Activity mWorkspace.clearDropTargets(); mWorkspace.removeAllWorkspaceScreens(); - mWidgetsToAdvance.clear(); if (mHotseat != null) { mHotseat.resetLayout(); } @@ -3984,14 +3873,6 @@ public class Launcher extends Activity if (LauncherAppState.PROFILE_STARTUP) { Trace.beginSection("Page bind completed"); } - if (mSavedState != null) { - if (!mWorkspace.hasFocus()) { - mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus(); - } - - mSavedState = null; - } - mWorkspace.restoreInstanceStateForRemainingPages(); setWorkspaceLoading(false); @@ -4413,7 +4294,6 @@ public class Launcher extends Activity */ public void dumpState() { Log.d(TAG, "BEGIN launcher3 dump state for launcher " + this); - Log.d(TAG, "mSavedState=" + mSavedState); Log.d(TAG, "mWorkspaceLoading=" + mWorkspaceLoading); Log.d(TAG, "mPendingRequestArgs=" + mPendingRequestArgs); Log.d(TAG, "mPendingActivityResult=" + mPendingActivityResult); @@ -4460,6 +4340,65 @@ public class Launcher extends Activity } } + @Override + @TargetApi(Build.VERSION_CODES.N) + public void onProvideKeyboardShortcuts( + List<KeyboardShortcutGroup> data, Menu menu, int deviceId) { + + ArrayList<KeyboardShortcutInfo> shortcutInfos = new ArrayList<>(); + if (mState == State.WORKSPACE) { + shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.all_apps_button_label), + KeyEvent.KEYCODE_A, KeyEvent.META_CTRL_ON)); + } + View currentFocus = getCurrentFocus(); + if (new CustomActionsPopup(this, currentFocus).canShow()) { + shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.custom_actions), + KeyEvent.KEYCODE_O, KeyEvent.META_CTRL_ON)); + } + if (currentFocus instanceof BubbleTextView && + ((BubbleTextView) currentFocus).hasDeepShortcuts()) { + shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.action_deep_shortcut), + KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON)); + } + if (!shortcutInfos.isEmpty()) { + data.add(new KeyboardShortcutGroup(getString(R.string.home_screen), shortcutInfos)); + } + + super.onProvideKeyboardShortcuts(data, menu, deviceId); + } + + @Override + public boolean onKeyShortcut(int keyCode, KeyEvent event) { + if (event.hasModifiers(KeyEvent.META_CTRL_ON)) { + switch (keyCode) { + case KeyEvent.KEYCODE_A: + if (mState == State.WORKSPACE) { + showAppsView(true, true, false); + return true; + } + break; + case KeyEvent.KEYCODE_S: { + View focusedView = getCurrentFocus(); + if (focusedView instanceof BubbleTextView + && focusedView.getTag() instanceof ItemInfo + && mAccessibilityDelegate.performAction(focusedView, + (ItemInfo) focusedView.getTag(), + LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) { + getOpenShortcutsContainer().requestFocus(); + return true; + } + break; + } + case KeyEvent.KEYCODE_O: + if (new CustomActionsPopup(this, getCurrentFocus()).show()) { + return true; + } + break; + } + } + return super.onKeyShortcut(keyCode, event); + } + public static CustomAppWidget getCustomAppWidget(String name) { return sCustomAppWidgets.get(name); } @@ -4468,14 +4407,6 @@ public class Launcher extends Activity return sCustomAppWidgets; } - public static List<View> getFolderContents(View icon) { - if (icon instanceof FolderIcon) { - return ((FolderIcon) icon).getFolder().getItemsInReadingOrder(); - } else { - return Collections.EMPTY_LIST; - } - } - public static Launcher getLauncher(Context context) { if (context instanceof Launcher) { return (Launcher) context; |