mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-27 23:19:02 +08:00
fix: use enhanced accessibilty node find method
This commit is contained in:
parent
07bdf02af4
commit
67b2a433a8
@ -268,7 +268,6 @@ class InputService : AccessibilityService() {
|
|||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
fun onKeyEvent(data: ByteArray) {
|
fun onKeyEvent(data: ByteArray) {
|
||||||
val keyEvent = KeyEvent.parseFrom(data)
|
val keyEvent = KeyEvent.parseFrom(data)
|
||||||
val down = keyEvent.getDown()
|
|
||||||
val keyboardMode = keyEvent.getMode()
|
val keyboardMode = keyEvent.getMode()
|
||||||
|
|
||||||
var textToCommit: String? = null
|
var textToCommit: String? = null
|
||||||
@ -306,66 +305,12 @@ class InputService : AccessibilityService() {
|
|||||||
} else {
|
} else {
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
handler.post {
|
handler.post {
|
||||||
findFocus(AccessibilityNodeInfo.FOCUS_INPUT)?.let { node ->
|
KeyEventConverter.toAndroidKeyEvent(keyEvent)?.let { event ->
|
||||||
val text = node.getText()
|
val possibleNodes = possibleAccessibiltyNodes()
|
||||||
val isShowingHint = node.isShowingHintText()
|
for (item in possibleNodes) {
|
||||||
|
val success = trySendKeyEvent(event, item, textToCommit)
|
||||||
var textSelectionStart = node.getTextSelectionStart()
|
if (success) {
|
||||||
var textSelectionEnd = node.getTextSelectionEnd()
|
break
|
||||||
|
|
||||||
if (text != null) {
|
|
||||||
if (textSelectionStart > text.length) {
|
|
||||||
textSelectionStart = text.length
|
|
||||||
}
|
|
||||||
if (textSelectionEnd > text.length) {
|
|
||||||
textSelectionEnd = text.length
|
|
||||||
}
|
|
||||||
if (textSelectionStart > textSelectionEnd) {
|
|
||||||
textSelectionStart = textSelectionEnd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textToCommit != null) {
|
|
||||||
var newText = ""
|
|
||||||
|
|
||||||
if ((textSelectionStart == -1) || (textSelectionEnd == -1)) {
|
|
||||||
newText = textToCommit
|
|
||||||
} else if (text != null) {
|
|
||||||
Log.d(logTag, "text selection start $textSelectionStart $textSelectionEnd")
|
|
||||||
newText = text.let {
|
|
||||||
it.substring(0, textSelectionStart) + textToCommit + it.substring(textSelectionStart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val arguments = Bundle()
|
|
||||||
arguments.putCharSequence(
|
|
||||||
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
|
|
||||||
newText
|
|
||||||
)
|
|
||||||
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
|
||||||
} else {
|
|
||||||
KeyEventConverter.toAndroidKeyEvent(keyEvent).let { event ->
|
|
||||||
if (isShowingHint) {
|
|
||||||
this.fakeEditTextForTextStateCalculation?.setText(null)
|
|
||||||
} else {
|
|
||||||
this.fakeEditTextForTextStateCalculation?.setText(text)
|
|
||||||
}
|
|
||||||
if (textSelectionStart != -1 && textSelectionEnd != -1) {
|
|
||||||
this.fakeEditTextForTextStateCalculation?.setSelection(
|
|
||||||
textSelectionStart,
|
|
||||||
textSelectionEnd
|
|
||||||
)
|
|
||||||
}
|
|
||||||
this.fakeEditTextForTextStateCalculation?.dispatchKeyEvent(event)
|
|
||||||
|
|
||||||
this.fakeEditTextForTextStateCalculation?.getText()?.let { newText ->
|
|
||||||
val arguments = Bundle()
|
|
||||||
arguments.putCharSequence(
|
|
||||||
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
|
|
||||||
newText.toString()
|
|
||||||
)
|
|
||||||
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,6 +318,165 @@ class InputService : AccessibilityService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun insertAccessibilityNode(list: LinkedList<AccessibilityNodeInfo>, node: AccessibilityNodeInfo) {
|
||||||
|
if (list.contains(node)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list.add(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findChildNode(node: AccessibilityNodeInfo?): AccessibilityNodeInfo? {
|
||||||
|
if (node == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (node.isEditable() && node.isFocusable()) {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
val childCount = node.getChildCount()
|
||||||
|
for (i in 0 until childCount) {
|
||||||
|
val child = node.getChild(i)
|
||||||
|
if (child != null) {
|
||||||
|
if (child.isEditable() && child.isFocusable()) {
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT < 33) {
|
||||||
|
child.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i in 0 until childCount) {
|
||||||
|
val child = node.getChild(i)
|
||||||
|
if (child != null) {
|
||||||
|
val result = findChildNode(child)
|
||||||
|
if (Build.VERSION.SDK_INT < 33) {
|
||||||
|
if (child != result) {
|
||||||
|
child.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun possibleAccessibiltyNodes(): LinkedList<AccessibilityNodeInfo> {
|
||||||
|
val linkedList = LinkedList<AccessibilityNodeInfo>()
|
||||||
|
val latestList = LinkedList<AccessibilityNodeInfo>()
|
||||||
|
|
||||||
|
val focusInput = findFocus(AccessibilityNodeInfo.FOCUS_INPUT)
|
||||||
|
var focusAccessibilityInput = findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY)
|
||||||
|
|
||||||
|
val rootInActiveWindow = getRootInActiveWindow()
|
||||||
|
|
||||||
|
if (focusInput != null) {
|
||||||
|
if (focusInput.isFocusable() && focusInput.isEditable()) {
|
||||||
|
insertAccessibilityNode(linkedList, focusInput)
|
||||||
|
} else {
|
||||||
|
insertAccessibilityNode(latestList, focusInput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (focusAccessibilityInput != null) {
|
||||||
|
if (focusAccessibilityInput.isFocusable() && focusAccessibilityInput.isEditable()) {
|
||||||
|
insertAccessibilityNode(linkedList, focusAccessibilityInput)
|
||||||
|
} else {
|
||||||
|
insertAccessibilityNode(latestList, focusAccessibilityInput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val childFromFocusInput = findChildNode(focusInput)
|
||||||
|
|
||||||
|
if (childFromFocusInput != null) {
|
||||||
|
insertAccessibilityNode(linkedList, childFromFocusInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
val childFromFocusAccessibilityInput = findChildNode(focusAccessibilityInput)
|
||||||
|
if (childFromFocusAccessibilityInput != null) {
|
||||||
|
insertAccessibilityNode(linkedList, childFromFocusAccessibilityInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootInActiveWindow != null) {
|
||||||
|
insertAccessibilityNode(linkedList, rootInActiveWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (item in latestList) {
|
||||||
|
insertAccessibilityNode(linkedList, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return linkedList
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun trySendKeyEvent(event: android.view.KeyEvent, node: AccessibilityNodeInfo, textToCommit: String?): Boolean {
|
||||||
|
node.refresh()
|
||||||
|
val text = node.getText()
|
||||||
|
var isShowingHint = false
|
||||||
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
|
isShowingHint = node.isShowingHintText()
|
||||||
|
}
|
||||||
|
|
||||||
|
var textSelectionStart = node.textSelectionStart
|
||||||
|
var textSelectionEnd = node.textSelectionEnd
|
||||||
|
|
||||||
|
if (text != null) {
|
||||||
|
if (textSelectionStart > text.length) {
|
||||||
|
textSelectionStart = text.length
|
||||||
|
}
|
||||||
|
if (textSelectionEnd > text.length) {
|
||||||
|
textSelectionEnd = text.length
|
||||||
|
}
|
||||||
|
if (textSelectionStart > textSelectionEnd) {
|
||||||
|
textSelectionStart = textSelectionEnd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var success = false
|
||||||
|
|
||||||
|
if (textToCommit != null) {
|
||||||
|
var newText = ""
|
||||||
|
|
||||||
|
if ((textSelectionStart == -1) || (textSelectionEnd == -1)) {
|
||||||
|
newText = textToCommit
|
||||||
|
} else if (text != null) {
|
||||||
|
Log.d(logTag, "text selection start $textSelectionStart $textSelectionEnd")
|
||||||
|
newText = text.let {
|
||||||
|
it.substring(0, textSelectionStart) + textToCommit + it.substring(textSelectionStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val arguments = Bundle()
|
||||||
|
arguments.putCharSequence(
|
||||||
|
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
|
||||||
|
newText
|
||||||
|
)
|
||||||
|
success = node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||||
|
} else {
|
||||||
|
if (isShowingHint) {
|
||||||
|
this.fakeEditTextForTextStateCalculation?.setText(null)
|
||||||
|
} else {
|
||||||
|
this.fakeEditTextForTextStateCalculation?.setText(text)
|
||||||
|
}
|
||||||
|
if (textSelectionStart != -1 && textSelectionEnd != -1) {
|
||||||
|
this.fakeEditTextForTextStateCalculation?.setSelection(
|
||||||
|
textSelectionStart,
|
||||||
|
textSelectionEnd
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this.fakeEditTextForTextStateCalculation?.dispatchKeyEvent(event)
|
||||||
|
|
||||||
|
this.fakeEditTextForTextStateCalculation?.getText()?.let { newText ->
|
||||||
|
val arguments = Bundle()
|
||||||
|
arguments.putCharSequence(
|
||||||
|
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
|
||||||
|
newText.toString()
|
||||||
|
)
|
||||||
|
success = node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
||||||
}
|
}
|
||||||
@ -381,7 +485,9 @@ class InputService : AccessibilityService() {
|
|||||||
super.onServiceConnected()
|
super.onServiceConnected()
|
||||||
ctx = this
|
ctx = this
|
||||||
val info = AccessibilityServiceInfo()
|
val info = AccessibilityServiceInfo()
|
||||||
info.flags = FLAG_INPUT_METHOD_EDITOR
|
if (Build.VERSION.SDK_INT >= 33) {
|
||||||
|
info.flags = FLAG_INPUT_METHOD_EDITOR
|
||||||
|
}
|
||||||
setServiceInfo(info)
|
setServiceInfo(info)
|
||||||
fakeEditTextForTextStateCalculation = EditText(this)
|
fakeEditTextForTextStateCalculation = EditText(this)
|
||||||
Log.d(logTag, "onServiceConnected!")
|
Log.d(logTag, "onServiceConnected!")
|
||||||
|
Loading…
Reference in New Issue
Block a user