diff options
author | Casey Burkhardt <caseyburkhardt@google.com> | 2010-08-08 20:08:39 -0700 |
---|---|---|
committer | Casey Burkhardt <caseyburkhardt@google.com> | 2010-08-08 20:08:39 -0700 |
commit | 79c6f8b2df9023bf46d6b2829ecf69bc4672566a (patch) | |
tree | 81cbc881845031a192f6b7f0de2177db0066a041 /src | |
parent | bb25b9e5b33c9ed7ce04e4dceb1c0f1f8b3e4036 (diff) | |
download | connectbot-79c6f8b2df9023bf46d6b2829ecf69bc4672566a.tar.gz connectbot-79c6f8b2df9023bf46d6b2829ecf69bc4672566a.tar.bz2 connectbot-79c6f8b2df9023bf46d6b2829ecf69bc4672566a.zip |
Improves accessibility by causing AccessibilityEvents to be fired after console changes occur.
Diffstat (limited to 'src')
-rwxr-xr-x[-rw-r--r--] | src/org/connectbot/TerminalView.java | 108 | ||||
-rw-r--r-- | src/org/connectbot/service/Relay.java | 4 | ||||
-rw-r--r-- | src/org/connectbot/service/TerminalBridge.java | 10 |
3 files changed, 118 insertions, 4 deletions
diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java index 35a3c56..057399f 100644..100755 --- a/src/org/connectbot/TerminalView.java +++ b/src/org/connectbot/TerminalView.java @@ -17,21 +17,29 @@ package org.connectbot; +import java.util.List; + import org.connectbot.bean.SelectionArea; import org.connectbot.service.FontSizeChangedListener; import org.connectbot.service.TerminalBridge; import org.connectbot.service.TerminalKeyListener; import android.app.Activity; +import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.database.Cursor; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelXorXfermode; import android.graphics.RectF; +import android.net.Uri; import android.view.View; import android.view.ViewGroup.LayoutParams; +import android.view.accessibility.AccessibilityEvent; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -63,6 +71,14 @@ public class TerminalView extends View implements FontSizeChangedListener { private String lastNotification = null; private volatile boolean notifications = true; + // Related to Accessibility Features + private boolean accessibilityActive = false; + private StringBuffer accessibilityBuffer = null; + private AccessibilityEventSender eventSender = null; + private int ACCESSIBILITY_EVENT_THRESHOLD = 1000; + private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; + private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; + public TerminalView(Context context, TerminalBridge bridge) { super(context); @@ -112,6 +128,9 @@ public class TerminalView extends View implements FontSizeChangedListener { // connect our view up to the bridge setOnKeyListener(bridge.getKeyHandler()); + + // Enable accessibility features if a screen reader is active. + accessibilityActive = isScreenReaderActive(); } public void destroy() { @@ -268,4 +287,93 @@ public class TerminalView extends View implements FontSizeChangedListener { outAttrs.inputType = EditorInfo.TYPE_NULL; return new BaseInputConnection(this, false); } + + private boolean isScreenReaderActive() { + // Restrict the set of intents to only accessibility services that have + // the category FEEDBACK_SPOKEN (aka, screen readers). + Intent screenReaderIntent = new Intent(SCREENREADER_INTENT_ACTION); + screenReaderIntent.addCategory(SCREENREADER_INTENT_CATEGORY); + List<ResolveInfo> screenReaders = context.getPackageManager().queryIntentServices( + screenReaderIntent, 0); + ContentResolver cr = context.getContentResolver(); + Cursor cursor = null; + int status = 0; + for (ResolveInfo screenReader : screenReaders) { + // All screen readers are expected to implement a content provider that responds to + // content://<nameofpackage>.providers.StatusProvider + cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName + + ".providers.StatusProvider"), null, null, null, null); + if (cursor != null) { + cursor.moveToFirst(); + // These content providers use a special cursor that only has one element, + // an integer that is 1 if the screen reader is running. + status = cursor.getInt(0); + cursor.close(); + if (status == 1) { + return true; + } + } + } + return false; + } + + + public StringBuffer getAccessibilityBuffer() { + return accessibilityBuffer; + } + + public void propagateConsoleText(char[] rawText, int length) { + if (accessibilityActive) { + if (accessibilityBuffer == null) { + accessibilityBuffer = new StringBuffer(); + } + + for (int i = 0; i < length; ++i) { + accessibilityBuffer.append(rawText[i]); + } + + if (eventSender != null) { + removeCallbacks(eventSender); + } else { + eventSender = new AccessibilityEventSender(); + } + postDelayed(eventSender, ACCESSIBILITY_EVENT_THRESHOLD); + } + } + + private class AccessibilityEventSender implements Runnable { + public void run() { + synchronized (accessibilityBuffer) { + // Strip Console Codes + String regex = "" + ((char) 27) + (char) 92 + ((char) 91) + "[^m]+[m|:]"; + accessibilityBuffer = + new StringBuffer(accessibilityBuffer.toString().replaceAll(regex, " ")); + + // Apply Backspaces + String backspaceCode = "" + ((char) 8) + ((char) 27) + ((char) 91) + ((char) 75); + int i = accessibilityBuffer.indexOf(backspaceCode); + while (i != -1) { + if (i == 0) { + accessibilityBuffer = + accessibilityBuffer.replace(i, i + backspaceCode.length(), ""); + } else { + accessibilityBuffer = + accessibilityBuffer.replace(i - 1, i + backspaceCode.length(), ""); + } + i = accessibilityBuffer.indexOf(backspaceCode); + } + + if (accessibilityBuffer.length() > 0) { + AccessibilityEvent event = + AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + event.setFromIndex(0); + event.setAddedCount(accessibilityBuffer.length()); + event.getText().add(accessibilityBuffer); + + sendAccessibilityEventUnchecked(event); + accessibilityBuffer.setLength(0); + } + } + } + } } diff --git a/src/org/connectbot/service/Relay.java b/src/org/connectbot/service/Relay.java index 18bf896..f14ff53 100644 --- a/src/org/connectbot/service/Relay.java +++ b/src/org/connectbot/service/Relay.java @@ -17,8 +17,6 @@ package org.connectbot.service; -import org.apache.harmony.niochar.charset.additional.IBM437; - import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -27,6 +25,7 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; +import org.apache.harmony.niochar.charset.additional.IBM437; import org.connectbot.transport.AbsTransport; import org.connectbot.util.EastAsianWidth; @@ -154,6 +153,7 @@ public class Relay implements Runnable { wideAttribute, isLegacyEastAsian); } buffer.putString(charArray, wideAttribute, 0, charBuffer.position()); + bridge.propagateConsoleText(charArray, charBuffer.position()); charBuffer.clear(); bridge.redraw(); } diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java index e9e69ca..9b4b96c 100644 --- a/src/org/connectbot/service/TerminalBridge.java +++ b/src/org/connectbot/service/TerminalBridge.java @@ -35,12 +35,12 @@ import org.connectbot.util.HostDatabase; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Typeface; -import android.graphics.Bitmap.Config; import android.graphics.Paint.FontMetrics; +import android.graphics.Typeface; import android.text.ClipboardManager; import android.util.Log; import de.mud.terminal.VDUBuffer; @@ -644,6 +644,12 @@ public class TerminalBridge implements VDUDisplay { return buffer; } + public void propagateConsoleText(char[] rawText, int length) { + if (parent != null) { + parent.propagateConsoleText(rawText, length); + } + } + public void onDraw() { int fg, bg; synchronized (buffer) { |