mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 19:38:21 +00:00
Merge "Filter recents view instances by package name" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
231e061ae1
@@ -28,6 +28,17 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/show_windows"
|
||||
android:layout_height="@dimen/recents_filter_icon_size"
|
||||
android:layout_width="@dimen/recents_filter_icon_size"
|
||||
android:layout_gravity="end"
|
||||
android:visibility="gone"
|
||||
android:tint="@color/recents_filter_icon"
|
||||
android:contentDescription="@string/recents_filter_icon_desc"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_select_windows" />
|
||||
|
||||
<com.android.quickstep.views.IconView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/task_thumbnail_icon_size"
|
||||
|
||||
@@ -38,6 +38,28 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/show_windows"
|
||||
android:layout_height="@dimen/recents_filter_icon_size"
|
||||
android:layout_width="@dimen/recents_filter_icon_size"
|
||||
android:layout_gravity="start"
|
||||
android:visibility="gone"
|
||||
android:tint="@color/recents_filter_icon"
|
||||
android:contentDescription="@string/recents_filter_icon_desc"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_select_windows" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/show_windows_right"
|
||||
android:layout_height="@dimen/recents_filter_icon_size"
|
||||
android:layout_width="@dimen/recents_filter_icon_size"
|
||||
android:layout_gravity="end"
|
||||
android:visibility="gone"
|
||||
android:tint="@color/recents_filter_icon"
|
||||
android:contentDescription="@string/recents_filter_icon_desc"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_select_windows" />
|
||||
|
||||
<com.android.quickstep.views.IconView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/task_thumbnail_icon_size"
|
||||
|
||||
@@ -76,4 +76,7 @@
|
||||
|
||||
<color name="all_set_page_background">#FFFFFFFF</color>
|
||||
|
||||
<!-- Recents overview -->
|
||||
<color name="recents_filter_icon">#333333</color>
|
||||
|
||||
</resources>
|
||||
@@ -306,6 +306,9 @@
|
||||
<dimen name="taskbar_button_margin_6_5">75dp</dimen>
|
||||
<dimen name="taskbar_button_margin_default">48dp</dimen>
|
||||
|
||||
<!-- Recents overview -->
|
||||
<dimen name="recents_filter_icon_size">30dp</dimen>
|
||||
|
||||
<!-- Launcher splash screen -->
|
||||
<!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
|
||||
<!-- starting_surface_exit_animation_window_shift_length -->
|
||||
|
||||
@@ -36,6 +36,13 @@
|
||||
<!-- Recents: Title of a button that clears the task list, i.e. closes all tasks. [CHAR LIMIT=30] -->
|
||||
<string name="recents_clear_all">Clear all</string>
|
||||
|
||||
<!-- Recents: Title of a button that goes back from displaying tasks filtered by package name to displaying all tasks [CHAR LIMIT=30] -->
|
||||
<string name="recents_back" translatable="false">Back</string>
|
||||
|
||||
<!-- TODO: b/260610444. Content description of filtering icons needs to be updated -->
|
||||
<!-- Recents: Content description for the icon on top of taskviews to initiate filtering -->
|
||||
<string name="recents_filter_icon_desc" translatable="false">Click to show only this app\'s tasks</string>
|
||||
|
||||
<!-- Accessibility title for the list of recent apps [CHAR_LIMIT=none] -->
|
||||
<string name="accessibility_recent_apps">Recent apps</string>
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages the recent task list from the system, caching it as necessary.
|
||||
@@ -129,14 +131,18 @@ public class RecentTasksList {
|
||||
* @return The change id of the current task list
|
||||
*/
|
||||
public synchronized int getTasks(boolean loadKeysOnly,
|
||||
Consumer<ArrayList<GroupTask>> callback) {
|
||||
Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
|
||||
final int requestLoadId = mChangeId;
|
||||
if (mResultsUi.isValidForRequest(requestLoadId, loadKeysOnly)) {
|
||||
// The list is up to date, send the callback on the next frame,
|
||||
// so that requestID can be returned first.
|
||||
if (callback != null) {
|
||||
// Copy synchronously as the changeId might change by next frame
|
||||
ArrayList<GroupTask> result = copyOf(mResultsUi);
|
||||
// and filter GroupTasks
|
||||
ArrayList<GroupTask> result = mResultsUi.stream().filter(filter)
|
||||
.map(GroupTask::copy)
|
||||
.collect(Collectors.toCollection(ArrayList<GroupTask>::new));
|
||||
|
||||
mMainThreadExecutor.post(() -> {
|
||||
callback.accept(result);
|
||||
});
|
||||
@@ -156,7 +162,11 @@ public class RecentTasksList {
|
||||
mLoadingTasksInBackground = false;
|
||||
mResultsUi = loadResult;
|
||||
if (callback != null) {
|
||||
ArrayList<GroupTask> result = copyOf(mResultsUi);
|
||||
// filter the tasks if needed before passing them into the callback
|
||||
ArrayList<GroupTask> result = mResultsUi.stream().filter(filter)
|
||||
.map(GroupTask::copy)
|
||||
.collect(Collectors.toCollection(ArrayList<GroupTask>::new));
|
||||
|
||||
callback.accept(result);
|
||||
}
|
||||
});
|
||||
|
||||
176
quickstep/src/com/android/quickstep/RecentsFilterState.java
Normal file
176
quickstep/src/com/android/quickstep/RecentsFilterState.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.quickstep;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.quickstep.util.GroupTask;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Keeps track of the state of {@code RecentsView}.
|
||||
*
|
||||
* <p> More specifically, used for keeping track of the state of filters applied on tasks
|
||||
* in {@code RecentsView} for multi-instance management.
|
||||
*/
|
||||
public class RecentsFilterState {
|
||||
// the minimum number of tasks per package present to allow filtering
|
||||
public static final int MIN_FILTERING_TASK_COUNT = 2;
|
||||
|
||||
// default filter that returns true for any input
|
||||
public static final Predicate<GroupTask> DEFAULT_FILTER = (groupTask -> true);
|
||||
|
||||
// the package name to filter recent tasks by
|
||||
@Nullable
|
||||
private String mPackageNameToFilter = null;
|
||||
|
||||
// the callback that gets executed upon filter change
|
||||
@Nullable
|
||||
private Runnable mOnFilterUpdatedListener = null;
|
||||
|
||||
// map maintaining the count for each unique base activity package name currently in the recents
|
||||
@Nullable
|
||||
private Map<String, Integer> mInstanceCountMap;
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@code RecentsView} filters tasks by some package name.
|
||||
*/
|
||||
public boolean isFiltered() {
|
||||
return mPackageNameToFilter != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the package name that tasks are filtered by.
|
||||
*/
|
||||
@Nullable
|
||||
public String getPackageNameToFilter() {
|
||||
return mPackageNameToFilter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a listener on any changes to the filter.
|
||||
*
|
||||
* @param callback listener to be executed upon filter updates
|
||||
*/
|
||||
public void setOnFilterUpdatedListener(@Nullable Runnable callback) {
|
||||
mOnFilterUpdatedListener = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the filter such that tasks are filtered by a certain package name.
|
||||
*
|
||||
* @param packageName package name of the base activity to filter tasks by;
|
||||
* if null, filter is turned off
|
||||
*/
|
||||
public void setFilterBy(@Nullable String packageName) {
|
||||
if (Objects.equals(packageName, mPackageNameToFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPackageNameToFilter = packageName;
|
||||
|
||||
if (mOnFilterUpdatedListener != null) {
|
||||
mOnFilterUpdatedListener.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the map of package names to their count in the most recent list of tasks.
|
||||
*
|
||||
* @param groupTaskList the list of tasks that map update is be based on
|
||||
*/
|
||||
public void updateInstanceCountMap(List<GroupTask> groupTaskList) {
|
||||
mInstanceCountMap = getInstanceCountMap(groupTaskList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of package names to their count in the most recent list of tasks.
|
||||
*/
|
||||
@Nullable
|
||||
public Map<String, Integer> getInstanceCountMap() {
|
||||
return mInstanceCountMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate for filtering out GroupTasks by package name.
|
||||
*
|
||||
* @param packageName package name to filter GroupTasks by
|
||||
* if null, Predicate always returns true.
|
||||
*/
|
||||
public static Predicate<GroupTask> getFilter(@Nullable String packageName) {
|
||||
if (packageName == null) {
|
||||
return DEFAULT_FILTER;
|
||||
}
|
||||
|
||||
return (groupTask) -> (groupTask.task2 != null
|
||||
&& groupTask.task2.key.getPackageName().equals(packageName))
|
||||
|| groupTask.task1.key.getPackageName().equals(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of package names to their frequencies in a list of GroupTasks.
|
||||
*
|
||||
* @param groupTasks the list to go through to create the map
|
||||
*/
|
||||
public static Map<String, Integer> getInstanceCountMap(List<GroupTask> groupTasks) {
|
||||
Map<String, Integer> instanceCountMap = new HashMap<>();
|
||||
|
||||
for (GroupTask groupTask : groupTasks) {
|
||||
final String firstTaskPkgName = groupTask.task1.key.getPackageName();
|
||||
final String secondTaskPkgName =
|
||||
groupTask.task2 == null ? null : groupTask.task2.key.getPackageName();
|
||||
|
||||
// increment the instance count for the first task's base activity package name
|
||||
incrementOrAddIfNotExists(instanceCountMap, firstTaskPkgName);
|
||||
|
||||
// check if second task is non existent
|
||||
if (secondTaskPkgName != null) {
|
||||
// increment the instance count for the second task's base activity package name
|
||||
incrementOrAddIfNotExists(instanceCountMap, secondTaskPkgName);
|
||||
}
|
||||
}
|
||||
|
||||
return instanceCountMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if tasks of provided package name should show filter UI.
|
||||
*
|
||||
* @param taskPackageName package name of the task in question
|
||||
*/
|
||||
public boolean shouldShowFilterUI(String taskPackageName) {
|
||||
// number of occurrences in recents overview with the package name of this task
|
||||
int instanceCount = getInstanceCountMap().get(taskPackageName);
|
||||
|
||||
// if the number of occurrences isn't enough make sure tasks can't be filtered by
|
||||
// the package name of this task
|
||||
return !(isFiltered() || instanceCount < MIN_FILTERING_TASK_COUNT);
|
||||
}
|
||||
|
||||
private static void incrementOrAddIfNotExists(Map<String, Integer> map, String pkgName) {
|
||||
if (!map.containsKey(pkgName)) {
|
||||
map.put(pkgName, 0);
|
||||
}
|
||||
map.put(pkgName, map.get(pkgName) + 1);
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Singleton class to load and manage recents model.
|
||||
@@ -104,7 +105,22 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener
|
||||
* @return the request id associated with this call.
|
||||
*/
|
||||
public int getTasks(Consumer<ArrayList<GroupTask>> callback) {
|
||||
return mTaskList.getTasks(false /* loadKeysOnly */, callback);
|
||||
return mTaskList.getTasks(false /* loadKeysOnly */, callback,
|
||||
RecentsFilterState.DEFAULT_FILTER);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the list of recent tasks, based on a filter
|
||||
*
|
||||
* @param callback The callback to receive the task plan once its complete or null. This is
|
||||
* always called on the UI thread.
|
||||
* @param filter Returns true if a GroupTask should be included into the list passed into
|
||||
* callback.
|
||||
* @return the request id associated with this call.
|
||||
*/
|
||||
public int getTasks(Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
|
||||
return mTaskList.getTasks(false /* loadKeysOnly */, callback, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,8 +142,9 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener
|
||||
* Checks if a task has been removed or not.
|
||||
*
|
||||
* @param callback Receives true if task is removed, false otherwise
|
||||
* @param filter Returns true if GroupTask should be in the list of considerations
|
||||
*/
|
||||
public void isTaskRemoved(int taskId, Consumer<Boolean> callback) {
|
||||
public void isTaskRemoved(int taskId, Consumer<Boolean> callback, Predicate<GroupTask> filter) {
|
||||
mTaskList.getTasks(true /* loadKeysOnly */, (taskGroups) -> {
|
||||
for (GroupTask group : taskGroups) {
|
||||
if (group.containsTask(taskId)) {
|
||||
@@ -136,7 +153,7 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener
|
||||
}
|
||||
}
|
||||
callback.accept(true);
|
||||
});
|
||||
}, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
@@ -102,6 +101,22 @@ public class GroupedTaskView extends TaskView {
|
||||
PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an on-click listener and the visibility for show_windows icon on top of each task.
|
||||
*/
|
||||
@Override
|
||||
public void setUpShowAllInstancesListener() {
|
||||
// sets up the listener for the left/top task
|
||||
super.setUpShowAllInstancesListener();
|
||||
|
||||
// right/bottom task's base package name
|
||||
String taskPackageName = mTaskIdAttributeContainer[1].getTask().key.getPackageName();
|
||||
|
||||
// icon of the right/bottom task
|
||||
View showWindowsView = findViewById(R.id.show_windows_right);
|
||||
updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskListVisibilityChanged(boolean visible, int changes) {
|
||||
super.onTaskListVisibilityChanged(visible, changes);
|
||||
|
||||
@@ -165,6 +165,7 @@ import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
import com.android.quickstep.RecentsFilterState;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.RemoteTargetGluer;
|
||||
@@ -581,7 +582,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
if (taskRemoved) {
|
||||
dismissTask(taskId);
|
||||
}
|
||||
});
|
||||
}, RecentsFilterState.getFilter(mFilterState.getPackageNameToFilter()));
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -722,6 +723,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
@Nullable
|
||||
private TaskLaunchListener mTaskLaunchListener;
|
||||
|
||||
// keeps track of the state of the filter for tasks in recents view
|
||||
private final RecentsFilterState mFilterState = new RecentsFilterState();
|
||||
|
||||
public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
|
||||
BaseActivityInterface sizeStrategy) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
@@ -785,6 +789,55 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
|
||||
|
||||
mTintingColor = getForegroundScrimDimColor(context);
|
||||
|
||||
// if multi-instance feature is enabled
|
||||
if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
|
||||
// invalidate the current list of tasks if filter changes
|
||||
mFilterState.setOnFilterUpdatedListener(this::invalidateTaskList);
|
||||
}
|
||||
// make sure filter is turned off by default
|
||||
mFilterState.setFilterBy(null);
|
||||
}
|
||||
|
||||
/** Get the state of the filter */
|
||||
public RecentsFilterState getFilterState() {
|
||||
return mFilterState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the filter and reloads the recents view if needed.
|
||||
*
|
||||
* @param packageName package name to filter by if the filter is being turned on;
|
||||
* should be null if filter is being turned off
|
||||
*/
|
||||
public void setAndApplyFilter(@Nullable String packageName) {
|
||||
mFilterState.setFilterBy(packageName);
|
||||
updateClearAllFunction();
|
||||
reloadIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "Clear All" button and its function depending on the recents view state.
|
||||
*
|
||||
* TODO: add a different button for going back to overview. Present solution is for demo only.
|
||||
*/
|
||||
public void updateClearAllFunction() {
|
||||
if (mFilterState.isFiltered()) {
|
||||
mClearAllButton.setText(R.string.recents_back);
|
||||
mClearAllButton.setOnClickListener((view) -> {
|
||||
this.setAndApplyFilter(null);
|
||||
});
|
||||
} else {
|
||||
mClearAllButton.setText(R.string.recents_clear_all);
|
||||
mClearAllButton.setOnClickListener(this::dismissAllTasks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the list of tasks so that an update occurs to the list of tasks if requested.
|
||||
*/
|
||||
private void invalidateTaskList() {
|
||||
mTaskListChangeId = -1;
|
||||
}
|
||||
|
||||
public OverScroller getScroller() {
|
||||
@@ -1547,6 +1600,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
Task stagedTaskToBeRemovedFromGrid =
|
||||
mSplitSelectSource != null ? mSplitSelectSource.alreadyRunningTask : null;
|
||||
|
||||
// update the map of instance counts
|
||||
mFilterState.updateInstanceCountMap(taskGroups);
|
||||
|
||||
// Add views as children based on whether it's grouped or single task. Looping through
|
||||
// taskGroups backwards populates the thumbnail grid from least recent to most recent.
|
||||
for (int i = taskGroups.size() - 1; i >= 0; i--) {
|
||||
@@ -1581,6 +1637,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
groupTask.mSplitBounds.leftTopTaskId == groupTask.task1.key.id;
|
||||
Task leftTopTask = firstTaskIsLeftTopTask ? groupTask.task1 : groupTask.task2;
|
||||
Task rightBottomTask = firstTaskIsLeftTopTask ? groupTask.task2 : groupTask.task1;
|
||||
|
||||
((GroupedTaskView) taskView).bind(leftTopTask, rightBottomTask, mOrientationState,
|
||||
groupTask.mSplitBounds);
|
||||
} else if (taskView instanceof DesktopTaskView) {
|
||||
@@ -1589,6 +1646,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
} else {
|
||||
taskView.bind(groupTask.task1, mOrientationState);
|
||||
}
|
||||
|
||||
// enables instance filtering if the feature flag for it is on
|
||||
if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
|
||||
taskView.setUpShowAllInstancesListener();
|
||||
}
|
||||
}
|
||||
|
||||
if (!taskGroups.isEmpty()) {
|
||||
@@ -2258,7 +2320,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
*/
|
||||
public void reloadIfNeeded() {
|
||||
if (!mModel.isTaskListValid(mTaskListChangeId)) {
|
||||
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan);
|
||||
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan, RecentsFilterState
|
||||
.getFilter(mFilterState.getPackageNameToFilter()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -526,6 +526,50 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
setOrientationState(orientedState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an on-click listener and the visibility for show_windows icon on top of the task.
|
||||
*/
|
||||
public void setUpShowAllInstancesListener() {
|
||||
String taskPackageName = mTaskIdAttributeContainer[0].mTask.key.getPackageName();
|
||||
|
||||
// icon of the top/left task
|
||||
View showWindowsView = findViewById(R.id.show_windows);
|
||||
updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callback that updates the state of the filter and the recents overview
|
||||
*
|
||||
* @param taskPackageName package name of the task to filter by
|
||||
*/
|
||||
@Nullable
|
||||
protected View.OnClickListener getFilterUpdateCallback(String taskPackageName) {
|
||||
View.OnClickListener cb = (view) -> {
|
||||
// update and apply a new filter
|
||||
getRecentsView().setAndApplyFilter(taskPackageName);
|
||||
};
|
||||
|
||||
if (!getRecentsView().getFilterState().shouldShowFilterUI(taskPackageName)) {
|
||||
cb = null;
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the correct visibility and callback on the provided filterView based on whether
|
||||
* the callback is null or not
|
||||
*/
|
||||
protected void updateFilterCallback(@NonNull View filterView,
|
||||
@Nullable View.OnClickListener callback) {
|
||||
if (callback == null) {
|
||||
filterView.setVisibility(GONE);
|
||||
} else {
|
||||
filterView.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
filterView.setOnClickListener(callback);
|
||||
}
|
||||
|
||||
public TaskIdAttributeContainer[] getTaskIdAttributeContainers() {
|
||||
return mTaskIdAttributeContainer;
|
||||
}
|
||||
|
||||
26
res/drawable/ic_select_windows.xml
Normal file
26
res/drawable/ic_select_windows.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 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="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M7,44Q5.8,44 4.9,43.1Q4,42.2 4,41V21.65Q4,20.45 4.9,19.55Q5.8,18.65 7,18.65H12.75V7Q12.75,5.8 13.65,4.9Q14.55,4 15.75,4H41Q42.2,4 43.1,4.9Q44,5.8 44,7V26.35Q44,27.55 43.1,28.45Q42.2,29.35 41,29.35H35.3V41Q35.3,42.2 34.4,43.1Q33.5,44 32.3,44ZM7,41H32.3Q32.3,41 32.3,41Q32.3,41 32.3,41V24.65H7V41Q7,41 7,41Q7,41 7,41ZM35.3,26.35H41Q41,26.35 41,26.35Q41,26.35 41,26.35V10H15.75V18.65H31.6Q33.2,18.65 34.25,19.7Q35.3,20.75 35.3,22.35Z"/>
|
||||
</vector>
|
||||
@@ -377,6 +377,10 @@ public final class FeatureFlags {
|
||||
"ENABLE_TASKBAR_EDU_TOOLTIP", false,
|
||||
"Enable the tooltip version of the Taskbar education flow.");
|
||||
|
||||
public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(
|
||||
"ENABLE_MULTI_INSTANCE", false,
|
||||
"Enables creation and filtering of multiple task instances in overview");
|
||||
|
||||
public static void initialize(Context context) {
|
||||
synchronized (sDebugFlags) {
|
||||
for (DebugFlag flag : sDebugFlags) {
|
||||
|
||||
Reference in New Issue
Block a user