Merge "Added open, dismiss and split screen as custom accessibility actions"
This commit is contained in:
committed by
Android (Google) Code Review
commit
85362e5f02
@@ -297,4 +297,11 @@
|
||||
If < 0, uses the value from HardwarePropertiesManager#getDeviceTemperatures. -->
|
||||
<integer name="config_warningTemperature">-1</integer>
|
||||
|
||||
<!-- Accessibility actions -->
|
||||
<item type="id" name="action_split_task_to_left" />
|
||||
<item type="id" name="action_split_task_to_right" />
|
||||
<item type="id" name="action_split_task_to_top" />
|
||||
<item type="id" name="action_open" />
|
||||
<item type="id" name="action_dimiss" />
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -794,6 +794,16 @@
|
||||
<string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string>
|
||||
<!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
|
||||
<string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
|
||||
<!-- Recents: Accessibility dismiss label -->
|
||||
<string name="recents_accessibility_dismissed">Dismiss</string>
|
||||
<!-- Recents: Accessibility open label -->
|
||||
<string name="recents_accessibility_open">Open</string>
|
||||
<!-- Recents: Accessibility split to the top -->
|
||||
<string name="recents_accessibility_split_screen_top">Split screen to the top</string>
|
||||
<!-- Recents: Accessibility split to the left -->
|
||||
<string name="recents_accessibility_split_screen_left">Split screen to the left</string>
|
||||
<!-- Recents: Accessibility split to the right -->
|
||||
<string name="recents_accessibility_split_screen_right">Split screen to the right</string>
|
||||
|
||||
<!-- Fully qualified activity class names to be blacklisted in Recents, add package names into overlay as needed -->
|
||||
<string-array name="recents_blacklist_array">
|
||||
|
||||
@@ -17,12 +17,33 @@
|
||||
package com.android.systemui.recents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import android.os.SystemProperties;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
|
||||
/**
|
||||
* Represents the dock regions for each orientation.
|
||||
*/
|
||||
class DockRegion {
|
||||
public static TaskStack.DockState[] PHONE_LANDSCAPE = {
|
||||
// We only allow docking to the left in landscape for now on small devices
|
||||
TaskStack.DockState.LEFT
|
||||
};
|
||||
public static TaskStack.DockState[] PHONE_PORTRAIT = {
|
||||
// We only allow docking to the top for now on small devices
|
||||
TaskStack.DockState.TOP
|
||||
};
|
||||
public static TaskStack.DockState[] TABLET_LANDSCAPE = {
|
||||
TaskStack.DockState.LEFT,
|
||||
TaskStack.DockState.RIGHT
|
||||
};
|
||||
public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Application resources that can be retrieved from the application context and are not specifically
|
||||
@@ -63,12 +84,14 @@ public class RecentsConfiguration {
|
||||
// Recents will layout task views in a grid mode when there's enough space in the screen.
|
||||
public boolean isGridEnabled;
|
||||
|
||||
private final Context mAppContext;
|
||||
|
||||
public RecentsConfiguration(Context context) {
|
||||
// Load only resources that can not change after the first load either through developer
|
||||
// settings or via multi window
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
Context appContext = context.getApplicationContext();
|
||||
Resources res = appContext.getResources();
|
||||
mAppContext = context.getApplicationContext();
|
||||
Resources res = mAppContext.getResources();
|
||||
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
|
||||
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
|
||||
isGridEnabled = SystemProperties.getBoolean("ro.recents.grid", false);
|
||||
@@ -86,4 +109,20 @@ public class RecentsConfiguration {
|
||||
public RecentsActivityLaunchState getLaunchState() {
|
||||
return mLaunchState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred dock states for the current orientation.
|
||||
* @return a list of dock states for device and its orientation
|
||||
*/
|
||||
public TaskStack.DockState[] getDockStatesForCurrentOrientation() {
|
||||
boolean isLandscape = mAppContext.getResources().getConfiguration().orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE;
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
if (config.isLargeScreen) {
|
||||
return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT;
|
||||
} else {
|
||||
return isLandscape ? DockRegion.PHONE_LANDSCAPE : DockRegion.PHONE_PORTRAIT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,10 +30,17 @@ public class DragStartEvent extends EventBus.Event {
|
||||
public final Task task;
|
||||
public final TaskView taskView;
|
||||
public final Point tlOffset;
|
||||
public final boolean isUserTouchInitiated;
|
||||
|
||||
public DragStartEvent(Task task, TaskView taskView, Point tlOffset) {
|
||||
this(task, taskView, tlOffset, true);
|
||||
}
|
||||
|
||||
public DragStartEvent(Task task, TaskView taskView, Point tlOffset,
|
||||
boolean isUserTouchInitiated) {
|
||||
this.task = task;
|
||||
this.taskView = taskView;
|
||||
this.tlOffset = tlOffset;
|
||||
this.isUserTouchInitiated = isUserTouchInitiated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ public class RecentsView extends FrameLayout {
|
||||
}
|
||||
|
||||
public final void onBusEvent(DragStartEvent event) {
|
||||
updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
|
||||
updateVisibleDockRegions(Recents.getConfiguration().getDockStatesForCurrentOrientation(),
|
||||
true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
|
||||
TaskStack.DockState.NONE.viewState.hintTextAlpha,
|
||||
true /* animateAlpha */, false /* animateBounds */);
|
||||
@@ -471,7 +471,8 @@ public class RecentsView extends FrameLayout {
|
||||
|
||||
public final void onBusEvent(DragDropTargetChangedEvent event) {
|
||||
if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) {
|
||||
updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
|
||||
updateVisibleDockRegions(
|
||||
Recents.getConfiguration().getDockStatesForCurrentOrientation(),
|
||||
true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
|
||||
TaskStack.DockState.NONE.viewState.hintTextAlpha,
|
||||
true /* animateAlpha */, true /* animateBounds */);
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.view.ViewDebug;
|
||||
|
||||
import com.android.internal.policy.DividerSnapAlgorithm;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.RecentsConfiguration;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
|
||||
import com.android.systemui.recents.events.activity.HideRecentsEvent;
|
||||
@@ -44,25 +43,6 @@ import com.android.systemui.recents.model.TaskStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents the dock regions for each orientation.
|
||||
*/
|
||||
class DockRegion {
|
||||
public static TaskStack.DockState[] PHONE_LANDSCAPE = {
|
||||
// We only allow docking to the left in landscape for now on small devices
|
||||
TaskStack.DockState.LEFT
|
||||
};
|
||||
public static TaskStack.DockState[] PHONE_PORTRAIT = {
|
||||
// We only allow docking to the top for now on small devices
|
||||
TaskStack.DockState.TOP
|
||||
};
|
||||
public static TaskStack.DockState[] TABLET_LANDSCAPE = {
|
||||
TaskStack.DockState.LEFT,
|
||||
TaskStack.DockState.RIGHT
|
||||
};
|
||||
public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles touch events for a RecentsView.
|
||||
*/
|
||||
@@ -110,20 +90,6 @@ public class RecentsViewTouchHandler {
|
||||
mDropTargets.add(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred dock states for the current orientation.
|
||||
*/
|
||||
public TaskStack.DockState[] getDockStatesForCurrentOrientation() {
|
||||
boolean isLandscape = mRv.getResources().getConfiguration().orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE;
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
if (config.isLargeScreen) {
|
||||
return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT;
|
||||
} else {
|
||||
return isLandscape ? DockRegion.PHONE_LANDSCAPE : DockRegion.PHONE_PORTRAIT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of visible dock states for this current drag.
|
||||
*/
|
||||
@@ -162,10 +128,14 @@ public class RecentsViewTouchHandler {
|
||||
mRv.getLocationInWindow(recentsViewLocation);
|
||||
mTaskViewOffset.set(mTaskView.getLeft() - recentsViewLocation[0] + event.tlOffset.x,
|
||||
mTaskView.getTop() - recentsViewLocation[1] + event.tlOffset.y);
|
||||
float x = mDownPos.x - mTaskViewOffset.x;
|
||||
float y = mDownPos.y - mTaskViewOffset.y;
|
||||
mTaskView.setTranslationX(x);
|
||||
mTaskView.setTranslationY(y);
|
||||
|
||||
// Change space coordinates relative to the view to RecentsView when user initiates a touch
|
||||
if (event.isUserTouchInitiated) {
|
||||
float x = mDownPos.x - mTaskViewOffset.x;
|
||||
float y = mDownPos.y - mTaskViewOffset.y;
|
||||
mTaskView.setTranslationX(x);
|
||||
mTaskView.setTranslationY(y);
|
||||
}
|
||||
|
||||
mVisibleDockStates.clear();
|
||||
if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
|
||||
@@ -176,7 +146,8 @@ public class RecentsViewTouchHandler {
|
||||
EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
|
||||
} else {
|
||||
// Add the dock state drop targets (these take priority)
|
||||
TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation();
|
||||
TaskStack.DockState[] dockStates = Recents.getConfiguration()
|
||||
.getDockStatesForCurrentOrientation();
|
||||
for (TaskStack.DockState dockState : dockStates) {
|
||||
registerDropTargetForCurrentDrag(dockState);
|
||||
dockState.update(mRv.getContext());
|
||||
|
||||
@@ -183,6 +183,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
}
|
||||
setOutlineProvider(mViewBounds);
|
||||
setOnLongClickListener(this);
|
||||
setAccessibilityDelegate(new TaskViewAccessibilityDelegate(this));
|
||||
}
|
||||
|
||||
/** Set callback */
|
||||
@@ -256,6 +257,11 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
|
||||
// Prevent any children from being focusable during talkback
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.recents.views;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
|
||||
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
|
||||
public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate {
|
||||
private static final String TAG = "TaskViewAccessibilityDelegate";
|
||||
|
||||
private final TaskView mTaskView;
|
||||
|
||||
protected static final int OPEN = R.id.action_open;
|
||||
protected static final int DIMISS = R.id.action_dimiss;
|
||||
protected static final int SPLIT_TASK_TOP = R.id.action_split_task_to_top;
|
||||
protected static final int SPLIT_TASK_LEFT = R.id.action_split_task_to_left;
|
||||
protected static final int SPLIT_TASK_RIGHT = R.id.action_split_task_to_right;
|
||||
|
||||
protected final SparseArray<AccessibilityAction> mActions = new SparseArray<>();
|
||||
|
||||
public TaskViewAccessibilityDelegate(TaskView taskView) {
|
||||
mTaskView = taskView;
|
||||
Context context = taskView.getContext();
|
||||
mActions.put(OPEN, new AccessibilityAction(OPEN,
|
||||
context.getString(R.string.recents_accessibility_open)));
|
||||
mActions.put(DIMISS, new AccessibilityAction(DIMISS,
|
||||
context.getString(R.string.recents_accessibility_dismissed)));
|
||||
mActions.put(SPLIT_TASK_TOP, new AccessibilityAction(SPLIT_TASK_TOP,
|
||||
context.getString(R.string.recents_accessibility_split_screen_top)));
|
||||
mActions.put(SPLIT_TASK_LEFT, new AccessibilityAction(SPLIT_TASK_LEFT,
|
||||
context.getString(R.string.recents_accessibility_split_screen_left)));
|
||||
mActions.put(SPLIT_TASK_RIGHT, new AccessibilityAction(SPLIT_TASK_RIGHT,
|
||||
context.getString(R.string.recents_accessibility_split_screen_right)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
info.addAction(mActions.get(OPEN));
|
||||
info.addAction(mActions.get(DIMISS));
|
||||
if (ActivityManager.supportsSplitScreenMultiWindow()
|
||||
&& !Recents.getSystemServices().hasDockedTask()) {
|
||||
TaskStack.DockState[] dockStates = Recents.getConfiguration()
|
||||
.getDockStatesForCurrentOrientation();
|
||||
for (TaskStack.DockState dockState: dockStates) {
|
||||
if (dockState == TaskStack.DockState.TOP) {
|
||||
info.addAction(mActions.get(SPLIT_TASK_TOP));
|
||||
} else if (dockState == TaskStack.DockState.LEFT) {
|
||||
info.addAction(mActions.get(SPLIT_TASK_LEFT));
|
||||
} else if (dockState == TaskStack.DockState.RIGHT) {
|
||||
info.addAction(mActions.get(SPLIT_TASK_RIGHT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(View host, int action, Bundle args) {
|
||||
if (action == OPEN) {
|
||||
mTaskView.onClick(host);
|
||||
} else if (action == DIMISS) {
|
||||
mTaskView.dismissTask();
|
||||
} else if (action == SPLIT_TASK_TOP) {
|
||||
simulateDragIntoMultiwindow(TaskStack.DockState.TOP);
|
||||
} else if (action == SPLIT_TASK_LEFT) {
|
||||
simulateDragIntoMultiwindow(TaskStack.DockState.LEFT);
|
||||
} else if (action == SPLIT_TASK_RIGHT) {
|
||||
simulateDragIntoMultiwindow(TaskStack.DockState.RIGHT);
|
||||
} else {
|
||||
return super.performAccessibilityAction(host, action, args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Simulate a user drag event to split the screen to the respected side */
|
||||
private void simulateDragIntoMultiwindow(TaskStack.DockState dockState) {
|
||||
int orientation = Utilities.getAppConfiguration(mTaskView.getContext()).orientation;
|
||||
EventBus.getDefault().send(new DragStartEvent(mTaskView.getTask(), mTaskView,
|
||||
new Point(0,0), false /* isUserTouchInitiated */));
|
||||
EventBus.getDefault().send(new DragEndEvent(mTaskView.getTask(), mTaskView, dockState));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user