summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--quickstep/res/drawable/ic_pin.xml26
-rw-r--r--quickstep/res/drawable/ic_split_screen.xml45
-rw-r--r--quickstep/res/values/strings.xml6
-rw-r--r--quickstep/src/com/android/quickstep/RecentsModel.java10
-rw-r--r--quickstep/src/com/android/quickstep/TaskMenuView.java36
-rw-r--r--quickstep/src/com/android/quickstep/TaskSystemShortcut.java98
-rw-r--r--quickstep/src/com/android/quickstep/TaskView.java11
-rw-r--r--quickstep/src/com/android/quickstep/TouchInteractionService.java1
8 files changed, 196 insertions, 37 deletions
diff --git a/quickstep/res/drawable/ic_pin.xml b/quickstep/res/drawable/ic_pin.xml
new file mode 100644
index 000000000..8c799e38e
--- /dev/null
+++ b/quickstep/res/drawable/ic_pin.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="#FFffffff"
+ android:pathData="M16,12L16,4l1,0L17,2L7,2l0,2l1,0l0,8l-2,2l0,2l5.2,0l0,6l1.6,0l0,-6L18,16l0,-2L16,12z"/>
+</vector> \ No newline at end of file
diff --git a/quickstep/res/drawable/ic_split_screen.xml b/quickstep/res/drawable/ic_split_screen.xml
new file mode 100644
index 000000000..77bd3336d
--- /dev/null
+++ b/quickstep/res/drawable/ic_split_screen.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="88.0dp"
+ android:height="88.0dp"
+ android:viewportWidth="88.0"
+ android:viewportHeight="88.0" >
+
+ <path
+ android:pathData="M 32,11
+ C 32,11 68,11 68,11
+ 76.74,11.06 76.98,12.76 77,21
+ 77.01,25.97 78.50,38.23 73.85,40.98
+ 71.80,42.19 68.35,42 66,42
+ 66,42 22,42 22,42
+ 18.82,41.99 14.87,42.38 12.60,39.69
+ 10.71,37.44 11.01,33.77 11,31
+ 10.99,25.54 9.53,16.08 13.31,12.02
+ 18.07,10.21 26.66,11 32,11 Z
+ M 32,46
+ C 32,46 68,46 68,46
+ 76.74,46.06 76.98,47.76 77,56
+ 77.01,60.97 78.50,73.23 73.85,75.98
+ 71.80,77.19 68.35,77 66,77
+ 66,77 22,77 22,77
+ 18.82,76.99 14.87,77.38 12.60,74.69
+ 10.71,72.44 11.01,68.77 11,66
+ 10.99,60.54 9.53,51.08 13.31,47.02
+ 18.07,45.21 26.66,46 32,46 Z"
+ android:fillColor="@android:color/white" />
+</vector> \ No newline at end of file
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index ef612268f..c2d6604b4 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -20,4 +20,10 @@
<!-- Application name -->
<string name="derived_app_name" translatable="false">Quickstep</string>
+
+ <!-- Options for recent tasks -->
+ <!-- Title for an option to enter split screen mode for a given app -->
+ <string name="recent_task_option_split_screen">Split screen</string>
+ <!-- Title for an option to keep an app pinned to the screen until it is unpinned -->
+ <string name="recent_task_option_pin">Pin</string>
</resources> \ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 22658b29d..d10c5a640 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -24,6 +24,7 @@ import android.os.UserHandle;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
+import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.PreloadOptions;
import com.android.systemui.shared.recents.model.RecentsTaskLoader;
@@ -66,6 +67,7 @@ public class RecentsModel extends TaskStackChangeListener {
private RecentsTaskLoadPlan mLastLoadPlan;
private int mLastLoadPlanId;
private int mTaskChangeId;
+ private ISystemUiProxy mSystemUiProxy;
private RecentsModel(Context context) {
mContext = context;
@@ -137,4 +139,12 @@ public class RecentsModel extends TaskStackChangeListener {
public RecentsTaskLoadPlan getLastLoadPlan() {
return mLastLoadPlan;
}
+
+ public void setSystemUiProxy(ISystemUiProxy systemUiProxy) {
+ mSystemUiProxy = systemUiProxy;
+ }
+
+ public ISystemUiProxy getSystemUiProxy() {
+ return mSystemUiProxy;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskMenuView.java b/quickstep/src/com/android/quickstep/TaskMenuView.java
index 196a2270f..52b240002 100644
--- a/quickstep/src/com/android/quickstep/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/TaskMenuView.java
@@ -40,7 +40,6 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
-import com.android.systemui.shared.recents.model.Task;
/**
* Contains options for a recent task when long-pressing its icon.
@@ -51,9 +50,10 @@ public class TaskMenuView extends AbstractFloatingView {
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[] {
- new TaskSystemShortcut.Widgets(),
new TaskSystemShortcut.AppInfo(),
- new TaskSystemShortcut.Install()
+ new TaskSystemShortcut.SplitScreen(),
+ new TaskSystemShortcut.Pin(),
+ new TaskSystemShortcut.Install(),
};
private static final long OPEN_CLOSE_DURATION = 220;
@@ -62,7 +62,6 @@ public class TaskMenuView extends AbstractFloatingView {
private TextView mTaskIconAndName;
private AnimatorSet mOpenCloseAnimator;
private TaskView mTaskView;
- private View mWidgetsOptionView;
public TaskMenuView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -133,21 +132,21 @@ public class TaskMenuView extends AbstractFloatingView {
}
mLauncher.getDragLayer().addView(this);
mTaskView = taskView;
- addMenuOptions(mTaskView.getTask());
+ addMenuOptions(mTaskView);
orientAroundTaskView(mTaskView);
post(this::animateOpen);
return true;
}
- private void addMenuOptions(Task task) {
- Drawable icon = task.icon.getConstantState().newDrawable();
+ private void addMenuOptions(TaskView taskView) {
+ Drawable icon = taskView.getTask().icon.getConstantState().newDrawable();
int iconSize = getResources().getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
icon.setBounds(0, 0, iconSize, iconSize);
mTaskIconAndName.setCompoundDrawables(null, icon, null, null);
- mTaskIconAndName.setText(TaskUtils.getTitle(mLauncher, task));
+ mTaskIconAndName.setText(TaskUtils.getTitle(mLauncher, taskView.getTask()));
for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
- OnClickListener onClickListener = menuOption.getOnClickListener(mLauncher, task);
+ OnClickListener onClickListener = menuOption.getOnClickListener(mLauncher, taskView);
if (onClickListener != null) {
addMenuOption(menuOption, onClickListener);
}
@@ -161,10 +160,6 @@ public class TaskMenuView extends AbstractFloatingView {
menuOptionView.getBubbleText().setText(menuOption.labelResId);
menuOptionView.setOnClickListener(onClickListener);
addView(menuOptionView);
-
- if (menuOption instanceof TaskSystemShortcut.Widgets) {
- mWidgetsOptionView = menuOptionView;
- }
}
private void orientAroundTaskView(TaskView taskView) {
@@ -231,19 +226,4 @@ public class TaskMenuView extends AbstractFloatingView {
}
};
}
-
- @Override
- protected void onWidgetsBound() {
- TaskSystemShortcut widgetsOption = new TaskSystemShortcut.Widgets();
- View.OnClickListener onClickListener = widgetsOption.getOnClickListener(
- mLauncher, mTaskView.getTask());
-
- if (onClickListener != null && mWidgetsOptionView == null) {
- // We didn't have any widgets cached but now there are some, so add the option.
- addMenuOption(widgetsOption, onClickListener);
- } else if (onClickListener == null && mWidgetsOptionView != null) {
- // No widgets exist, but we previously added the option so remove it.
- removeView(mWidgetsOptionView);
- }
- }
}
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index 1ba7ce4e1..9200eeb06 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -16,23 +16,37 @@
package com.android.quickstep;
+import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
import android.view.View;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.InstantAppResolver;
+import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.ActivityOptionsCompat;
+
+import java.util.function.Consumer;
/**
* Represents a system shortcut that can be shown for a recent task.
*/
public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut {
+ private static final String TAG = "TaskSystemShortcut";
+
protected T mSystemShortcut;
protected TaskSystemShortcut(T systemShortcut) {
@@ -40,12 +54,18 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
mSystemShortcut = systemShortcut;
}
+ protected TaskSystemShortcut(int iconResId, int labelResId) {
+ super(iconResId, labelResId);
+ }
+
@Override
public View.OnClickListener getOnClickListener(Launcher launcher, ItemInfo itemInfo) {
return null;
}
- public View.OnClickListener getOnClickListener(final Launcher launcher, final Task task) {
+ public View.OnClickListener getOnClickListener(final Launcher launcher, final TaskView view) {
+ Task task = view.getTask();
+
ShortcutInfo dummyInfo = new ShortcutInfo();
dummyInfo.intent = new Intent();
ComponentName component = task.getTopComponent();
@@ -61,16 +81,80 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
return mSystemShortcut.getOnClickListener(launcher, dummyInfo);
}
+ public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> {
+ public AppInfo() {
+ super(new SystemShortcut.AppInfo());
+ }
+ }
+
+ public static class SplitScreen extends TaskSystemShortcut {
+
+ private Handler mHandler;
+
+ public SplitScreen() {
+ super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+
+ @Override
+ public View.OnClickListener getOnClickListener(Launcher launcher, TaskView taskView) {
+ if (launcher.getDeviceProfile().inMultiWindowMode()) {
+ return null;
+ }
+ return (v -> {
+ Task task = taskView.getTask();
+ final ActivityOptions options = ActivityOptionsCompat.makeSplitScreenOptions(true);
+ final Consumer<Boolean> resultCallback = success -> {
+ if (success) {
+ launcher.<RecentsView>getOverviewPanel().removeView(taskView);
+ }
+ };
+ ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(
+ task.key, options, resultCallback, mHandler);
- public static class Widgets extends TaskSystemShortcut<SystemShortcut.Widgets> {
- public Widgets() {
- super(new SystemShortcut.Widgets());
+ // TODO improve transition; see:
+ // DockedFirstAnimationFrameEvent
+ // RecentsTransitionHelper#composeDockAnimationSpec
+ // WindowManagerWrapper#overridePendingAppTransitionMultiThumbFuture
+ });
}
}
- public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> {
- public AppInfo() {
- super(new SystemShortcut.AppInfo());
+ public static class Pin extends TaskSystemShortcut {
+
+ // Same as Settings.System.LOCK_TO_APP_ENABLED, which is hidden.
+ // TODO use call from shared lib instead
+ private static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled";
+
+ private Handler mHandler;
+
+ public Pin() {
+ super(R.drawable.ic_pin, R.string.recent_task_option_pin);
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+
+ @Override
+ public View.OnClickListener getOnClickListener(Launcher launcher, TaskView taskView) {
+ ISystemUiProxy sysUiProxy = RecentsModel.getInstance(launcher).getSystemUiProxy();
+ if (sysUiProxy == null) {
+ return null;
+ }
+ if (Settings.System.getInt(launcher.getContentResolver(),
+ LOCK_TO_APP_ENABLED, 0) == 0) {
+ return null;
+ }
+ return view -> {
+ Consumer<Boolean> resultCallback = success -> {
+ if (success) {
+ try {
+ sysUiProxy.startScreenPinning(taskView.getTask().key.id);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to start screen pinning: ", e);
+ }
+ }
+ };
+ taskView.launchTask(true, resultCallback, mHandler);
+ };
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskView.java b/quickstep/src/com/android/quickstep/TaskView.java
index 46fcc724c..6a70e2d63 100644
--- a/quickstep/src/com/android/quickstep/TaskView.java
+++ b/quickstep/src/com/android/quickstep/TaskView.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
+import android.os.Handler;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;
@@ -36,7 +37,6 @@ import android.widget.ImageView;
import com.android.launcher3.R;
import com.android.quickstep.RecentsView.PageCallbacks;
import com.android.quickstep.RecentsView.ScrollState;
-import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskCallbacks;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -47,6 +47,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
/**
* A task in the Recents view.
@@ -127,6 +128,11 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
}
public void launchTask(boolean animate) {
+ launchTask(animate, null, null);
+ }
+
+ public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
+ Handler resultCallbackHandler) {
if (mTask != null) {
final ActivityOptions opts;
if (animate) {
@@ -154,7 +160,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
opts = ActivityOptions.makeCustomAnimation(getContext(), 0, 0);
}
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
- opts, null, null);
+ opts, resultCallback, resultCallbackHandler);
}
}
@@ -162,6 +168,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
public void onTaskDataLoaded(Task task, ThumbnailData thumbnailData) {
mSnapshotView.setThumbnail(task, thumbnailData);
mIconView.setImageDrawable(task.icon);
+ mIconView.setOnClickListener(icon -> TaskMenuView.showForTask(this));
mIconView.setOnLongClickListener(icon -> TaskMenuView.showForTask(this));
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 049083217..67146ff8d 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -110,6 +110,7 @@ public class TouchInteractionService extends Service {
@Override
public void onBind(ISystemUiProxy iSystemUiProxy) {
mISystemUiProxy = iSystemUiProxy;
+ mRecentsModel.setSystemUiProxy(mISystemUiProxy);
}
@Override