Skip to content

Commit 6e8f9d9

Browse files
Accessibility: add compatibility with multiple displays
1 parent ef0153f commit 6e8f9d9

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

app/src/main/java/com/termux/api/apis/AccessibilityAPI.java

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
import android.content.pm.ServiceInfo;
3737
import java.util.List;
3838
import android.accessibilityservice.AccessibilityService;
39+
import android.view.accessibility.AccessibilityWindowInfo;
40+
import android.util.SparseArray;
41+
3942
import android.os.Bundle;
4043

4144
import android.view.Display;
@@ -62,10 +65,12 @@ public static void onReceive(TermuxApiReceiver apiReceiver, final Context contex
6265
context.startActivity(accessibilityIntent);
6366
}
6467

68+
int displayId = intent.getIntExtra("display-id", Display.DEFAULT_DISPLAY);
69+
6570
if (intent.hasExtra("dump")) {
66-
dump(apiReceiver, intent);
71+
dump(apiReceiver, intent, displayId);
6772
} else if (intent.hasExtra("click")) {
68-
click(intent.getIntExtra("x", 0), intent.getIntExtra("y", 0), intent.getIntExtra("duration", 1));
73+
click(intent.getIntExtra("x", 0), intent.getIntExtra("y", 0), intent.getIntExtra("duration", 1), displayId);
6974
returnEmptyString(apiReceiver, intent);
7075
} else if (intent.hasExtra("type")) {
7176
type(intent.getStringExtra("type"));
@@ -74,7 +79,7 @@ public static void onReceive(TermuxApiReceiver apiReceiver, final Context contex
7479
performGlobalAction(intent.getStringExtra("global-action"));
7580
returnEmptyString(apiReceiver, intent);
7681
} else if (intent.hasExtra("screenshot")) {
77-
screenshot(apiReceiver, context, intent);
82+
screenshot(apiReceiver, context, intent, displayId);
7883
}
7984
}
8085

@@ -97,22 +102,20 @@ public static boolean isAccessibilityServiceEnabled(Context context, Class<? ext
97102
return false;
98103
}
99104

100-
private static void click(int x, int y, int millisecondsDuration) {
105+
private static void click(int x, int y, int millisecondsDuration, int displayId) {
101106
Path swipePath = new Path();
102107
swipePath.moveTo(x, y);
103108
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
109+
gestureBuilder.setDisplayId(displayId);
104110
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, millisecondsDuration));
105111
TermuxAccessibilityService.instance.dispatchGesture(gestureBuilder.build(), null, null);
106112
}
107113

108114
// The aim of this function is to give a compatible output with `adb` `uiautomator dump`.
109-
private static void dump(TermuxApiReceiver apiReceiver, Intent intent) {
110-
AccessibilityNodeInfo node = TermuxAccessibilityService.instance.getRootInActiveWindow();
111-
// On Signal *App permissions* for instance
112-
if (node == null) {
113-
ResultReturner.returnData(apiReceiver, intent, out -> {});
114-
return;
115-
}
115+
private static void dump(TermuxApiReceiver apiReceiver, Intent intent, int displayId) {
116+
SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays = TermuxAccessibilityService.instance.getWindowsOnAllDisplays();
117+
List<AccessibilityWindowInfo> windowsOnDisplay = windowsOnAllDisplays.get(displayId);
118+
AccessibilityNodeInfo node = windowsOnDisplay.getLast().getRoot();
116119

117120
String swString = dumpAuxiliary(node);
118121

@@ -225,10 +228,22 @@ private static String getCharSequenceAsString(CharSequence charSequence) {
225228
}
226229

227230
private static void type(String toType) {
228-
AccessibilityNodeInfo focusedNode = TermuxAccessibilityService.instance.getRootInActiveWindow().findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
229-
Bundle arguments = new Bundle();
230-
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, toType);
231-
focusedNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
231+
SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays = TermuxAccessibilityService.instance.getWindowsOnAllDisplays();
232+
for(int windowsOnAllDisplayIndex = 0; windowsOnAllDisplayIndex < windowsOnAllDisplays.size(); windowsOnAllDisplayIndex++)
233+
{
234+
List<AccessibilityWindowInfo> windowsOnAllDisplay = windowsOnAllDisplays.valueAt(windowsOnAllDisplayIndex);
235+
for(AccessibilityWindowInfo accessibilityWindowInfo : windowsOnAllDisplay)
236+
{
237+
AccessibilityNodeInfo focusedNode = accessibilityWindowInfo.getRoot().findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
238+
if(focusedNode != null)
239+
{
240+
Bundle arguments = new Bundle();
241+
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, toType);
242+
focusedNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
243+
return;
244+
}
245+
}
246+
}
232247
}
233248

234249
private static void performGlobalAction(String globalActionString) {
@@ -249,9 +264,9 @@ private static void performGlobalAction(String globalActionString) {
249264
TermuxAccessibilityService.instance.performGlobalAction(globalActionInt);
250265
}
251266

252-
private static void screenshot(TermuxApiReceiver apiReceiver, final Context context, Intent intent) {
267+
private static void screenshot(TermuxApiReceiver apiReceiver, final Context context, Intent intent, int displayId) {
253268
TermuxAccessibilityService.instance.takeScreenshot(
254-
Display.DEFAULT_DISPLAY,
269+
displayId,
255270
context.getMainExecutor(),
256271
new TakeScreenshotCallback() {
257272

app/src/main/res/xml/accessibility_service_config.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
<accessibility-service
33
xmlns:android="http://schemas.android.com/apk/res/android"
44
android:canRetrieveWindowContent="true"
5-
android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"
5+
android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews|flagRetrieveInteractiveWindows"
66
android:canPerformGestures="true"
77
android:canTakeScreenshot="true"/>

0 commit comments

Comments
 (0)