Mercurial > 510Connectbot
annotate app/src/main/java/com/five_ten_sg/connectbot/TerminalView.java @ 506:b8cc360e1550 stable-1.9.4-5
allow multiple screen watch areas
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 16 Nov 2022 12:05:29 -0700 |
parents | 105815cce146 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * ConnectBot: simple, powerful, open-source SSH client for Android | |
3 * Copyright 2007 Kenny Root, Jeffrey Sharkey | |
4 * | |
5 * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 * you may not use this file except in compliance with the License. | |
7 * You may obtain a copy of the License at | |
8 * | |
9 * http://www.apache.org/licenses/LICENSE-2.0 | |
10 * | |
11 * Unless required by applicable law or agreed to in writing, software | |
12 * distributed under the License is distributed on an "AS IS" BASIS, | |
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 * See the License for the specific language governing permissions and | |
15 * limitations under the License. | |
16 */ | |
17 | |
18 package com.five_ten_sg.connectbot; | |
19 | |
20 import java.util.List; | |
21 import java.util.regex.Matcher; | |
22 import java.util.regex.Pattern; | |
23 | |
24 import com.five_ten_sg.connectbot.bean.SelectionArea; | |
25 import com.five_ten_sg.connectbot.service.FontSizeChangedListener; | |
26 import com.five_ten_sg.connectbot.service.TerminalBridge; | |
27 import com.five_ten_sg.connectbot.service.TerminalKeyListener; | |
28 import android.app.Activity; | |
29 import android.content.ContentResolver; | |
30 import android.content.Context; | |
31 import android.content.Intent; | |
32 import android.content.pm.ResolveInfo; | |
33 import android.database.Cursor; | |
34 import android.graphics.Canvas; | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
35 import android.graphics.ColorMatrix; |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
36 import android.graphics.ColorMatrixColorFilter; |
0 | 37 import android.graphics.Matrix; |
38 import android.graphics.Paint; | |
39 import android.graphics.Path; | |
40 import android.graphics.RectF; | |
41 import android.net.Uri; | |
42 import android.os.AsyncTask; | |
420
e5f7c2584296
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
419
diff
changeset
|
43 import android.util.Log; |
0 | 44 import android.view.KeyEvent; |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
45 import android.view.ScaleGestureDetector; |
0 | 46 import android.view.View; |
47 import android.view.ViewGroup.LayoutParams; | |
48 import android.view.accessibility.AccessibilityEvent; | |
49 import android.view.accessibility.AccessibilityManager; | |
50 import android.view.inputmethod.BaseInputConnection; | |
51 import android.view.inputmethod.EditorInfo; | |
52 import android.view.inputmethod.InputConnection; | |
53 import android.widget.Toast; | |
54 import de.mud.terminal.VDUBuffer; | |
55 | |
56 /** | |
57 * User interface {@link View} for showing a TerminalBridge in an | |
58 * {@link Activity}. Handles drawing bitmap updates and passing keystrokes down | |
59 * to terminal. | |
60 * | |
61 * @author jsharkey | |
62 */ | |
63 public class TerminalView extends View implements FontSizeChangedListener { | |
420
e5f7c2584296
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
419
diff
changeset
|
64 public final static String TAG = "ConnectBot.TerminalView"; |
0 | 65 |
66 private final Context context; | |
91
33eb63352be5
remove 5250 configuration
Carl Byington <carl@five-ten-sg.com>
parents:
23
diff
changeset
|
67 public final TerminalBridge bridge; |
0 | 68 private final Paint paint; |
69 private final Paint cursorPaint; | |
70 private final Paint cursorStrokePaint; | |
71 | |
72 // Cursor paints to distinguish modes | |
73 private Path ctrlCursor, altCursor, shiftCursor; | |
74 private RectF tempSrc, tempDst; | |
75 private Matrix scaleMatrix; | |
76 private static final Matrix.ScaleToFit scaleType = Matrix.ScaleToFit.FILL; | |
77 | |
419
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
78 private Toast notification = null; |
0 | 79 private String lastNotification = null; |
80 private volatile boolean notifications = true; | |
81 | |
82 // Related to Accessibility Features | |
83 private boolean mAccessibilityInitialized = false; | |
84 private boolean mAccessibilityActive = true; | |
85 private Object[] mAccessibilityLock = new Object[0]; | |
86 private StringBuffer mAccessibilityBuffer; | |
87 private Pattern mControlCodes = null; | |
88 private Matcher mCodeMatcher = null; | |
89 private AccessibilityEventSender mEventSender = null; | |
90 | |
23 | 91 |
0 | 92 private static final String BACKSPACE_CODE = "\\x08\\x1b\\[K"; |
93 private static final String CONTROL_CODE_PATTERN = "\\x1b\\[K[^m]+[m|:]"; | |
94 | |
95 private static final int ACCESSIBILITY_EVENT_THRESHOLD = 1000; | |
96 private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; | |
97 private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; | |
98 | |
99 public ScaleGestureDetector mScaleDetector; | |
100 | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
101 private ColorMatrix getColorMatrix() { |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
102 return new ColorMatrix(new float[] { |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
103 -1, 0, 0, 0, 255, |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
104 0, -1, 0, 0, 255, |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
105 0, 0, -1, 0, 255, |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
106 0, 0, 0, 1, 0 |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
107 }); |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
108 } |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
109 |
0 | 110 public TerminalView(Context context, TerminalBridge bridge) { |
111 super(context); | |
91
33eb63352be5
remove 5250 configuration
Carl Byington <carl@five-ten-sg.com>
parents:
23
diff
changeset
|
112 this.context = context; |
33eb63352be5
remove 5250 configuration
Carl Byington <carl@five-ten-sg.com>
parents:
23
diff
changeset
|
113 this.bridge = bridge; |
0 | 114 paint = new Paint(); |
115 setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); | |
116 setFocusable(true); | |
117 setFocusableInTouchMode(true); | |
118 cursorPaint = new Paint(); | |
119 cursorPaint.setColor(bridge.color[bridge.defaultFg]); | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
120 cursorPaint.setColorFilter(new ColorMatrixColorFilter(getColorMatrix())); |
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
121 //cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[bridge.defaultBg])); |
0 | 122 cursorPaint.setAntiAlias(true); |
123 cursorStrokePaint = new Paint(cursorPaint); | |
124 cursorStrokePaint.setStrokeWidth(0.1f); | |
125 cursorStrokePaint.setStyle(Paint.Style.STROKE); | |
126 /* | |
127 * Set up our cursor indicators on a 1x1 Path object which we can later | |
128 * transform to our character width and height | |
129 */ | |
130 // TODO make this into a resource somehow | |
131 shiftCursor = new Path(); | |
132 shiftCursor.lineTo(0.5f, 0.33f); | |
133 shiftCursor.lineTo(1.0f, 0.0f); | |
134 altCursor = new Path(); | |
135 altCursor.moveTo(0.0f, 1.0f); | |
136 altCursor.lineTo(0.5f, 0.66f); | |
137 altCursor.lineTo(1.0f, 1.0f); | |
138 ctrlCursor = new Path(); | |
139 ctrlCursor.moveTo(0.0f, 0.25f); | |
140 ctrlCursor.lineTo(1.0f, 0.5f); | |
141 ctrlCursor.lineTo(0.0f, 0.75f); | |
142 // For creating the transform when the terminal resizes | |
143 tempSrc = new RectF(); | |
144 tempSrc.set(0.0f, 0.0f, 1.0f, 1.0f); | |
145 tempDst = new RectF(); | |
146 scaleMatrix = new Matrix(); | |
147 bridge.addFontSizeChangedListener(this); | |
148 // connect our view up to the bridge | |
149 setOnKeyListener(bridge.getKeyHandler()); | |
150 mAccessibilityBuffer = new StringBuffer(); | |
151 // Enable accessibility features if a screen reader is active. | |
152 new AccessibilityStateTester().execute((Void) null); | |
153 mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); | |
154 } | |
155 | |
156 public void destroy() { | |
157 // tell bridge to destroy its bitmap | |
158 bridge.parentDestroyed(); | |
159 } | |
160 | |
161 @Override | |
162 protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
163 super.onSizeChanged(w, h, oldw, oldh); | |
164 bridge.parentChanged(this); | |
165 scaleCursors(); | |
166 } | |
167 | |
168 public void onFontSizeChanged(float size) { | |
169 scaleCursors(); | |
170 } | |
171 | |
172 private void scaleCursors() { | |
173 // Create a scale matrix to scale our 1x1 representation of the cursor | |
174 tempDst.set(0.0f, 0.0f, bridge.charWidth, bridge.charHeight); | |
175 scaleMatrix.setRectToRect(tempSrc, tempDst, scaleType); | |
176 } | |
177 | |
178 @Override | |
179 public void onDraw(Canvas canvas) { | |
180 if (bridge.bitmap != null) { | |
181 // draw the bitmap | |
182 bridge.onDraw(); | |
183 // draw the bridge bitmap if it exists | |
184 canvas.drawBitmap(bridge.bitmap, 0, 0, paint); | |
185 | |
186 // also draw cursor if visible | |
187 if (bridge.buffer.isCursorVisible()) { | |
188 int cursorColumn = bridge.buffer.getCursorColumn(); | |
189 final int cursorRow = bridge.buffer.getCursorRow(); | |
190 final int columns = bridge.buffer.getColumns(); | |
191 | |
192 if (cursorColumn == columns) | |
193 cursorColumn = columns - 1; | |
194 | |
195 if (cursorColumn < 0 || cursorRow < 0) | |
196 return; | |
197 | |
198 int currentAttribute = bridge.buffer.getAttributes( | |
199 cursorColumn, cursorRow); | |
200 boolean onWideCharacter = (currentAttribute & VDUBuffer.FULLWIDTH) != 0; | |
201 int x = cursorColumn * bridge.charWidth; | |
202 int y = (bridge.buffer.getCursorRow() | |
203 + bridge.buffer.screenBase - bridge.buffer.windowBase) | |
204 * bridge.charHeight; | |
205 // Save the current clip and translation | |
206 canvas.save(); | |
207 canvas.translate(x, y); | |
208 canvas.clipRect(0, 0, | |
209 bridge.charWidth * (onWideCharacter ? 2 : 1), | |
210 bridge.charHeight); | |
211 canvas.drawPaint(cursorPaint); | |
212 final int deadKey = bridge.getKeyHandler().getDeadKey(); | |
213 | |
214 if (deadKey != 0) { | |
215 canvas.drawText(new char[] { (char)deadKey }, 0, 1, 0, 0, cursorStrokePaint); | |
216 } | |
217 | |
218 // Make sure we scale our decorations to the correct size. | |
219 canvas.concat(scaleMatrix); | |
220 int metaState = bridge.getKeyHandler().getMetaState(); | |
221 | |
222 if ((metaState & TerminalKeyListener.META_SHIFT_ON) != 0) | |
223 canvas.drawPath(shiftCursor, cursorStrokePaint); | |
224 else if ((metaState & TerminalKeyListener.META_SHIFT_LOCK) != 0) | |
225 canvas.drawPath(shiftCursor, cursorPaint); | |
226 | |
227 if ((metaState & TerminalKeyListener.META_ALT_ON) != 0) | |
228 canvas.drawPath(altCursor, cursorStrokePaint); | |
229 else if ((metaState & TerminalKeyListener.META_ALT_LOCK) != 0) | |
230 canvas.drawPath(altCursor, cursorPaint); | |
231 | |
232 if ((metaState & TerminalKeyListener.META_CTRL_ON) != 0) | |
233 canvas.drawPath(ctrlCursor, cursorStrokePaint); | |
234 else if ((metaState & TerminalKeyListener.META_CTRL_LOCK) != 0) | |
235 canvas.drawPath(ctrlCursor, cursorPaint); | |
236 | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
237 canvas.restore(); // Restore previous clip region |
0 | 238 } |
239 | |
240 // draw any highlighted area | |
241 if (bridge.isSelectingForCopy()) { | |
242 SelectionArea area = bridge.getSelectionArea(); | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
243 canvas.save(); |
0 | 244 canvas.clipRect( |
245 area.getLeft() * bridge.charWidth, | |
246 area.getTop() * bridge.charHeight, | |
247 (area.getRight() + 1) * bridge.charWidth, | |
248 (area.getBottom() + 1) * bridge.charHeight | |
249 ); | |
250 canvas.drawPaint(cursorPaint); | |
251 canvas.restore(); | |
252 } | |
253 } | |
254 } | |
255 | |
256 public void notifyUser(String message) { | |
419
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
257 try { |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
258 // ignore if don't want notifications |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
259 if (!notifications) return; |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
260 // Don't keep telling the user the same thing. |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
261 if (lastNotification != null && lastNotification.equals(message)) return; |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
262 // create or use old toast |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
263 if (notification == null) { |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
264 notification = Toast.makeText(context, message, Toast.LENGTH_SHORT); |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
265 } |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
266 else { |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
267 notification.setText(message); |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
268 } |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
269 notification.show(); |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
270 lastNotification = message; |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
271 } |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
272 catch (Exception e) { |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
273 Log.e(TAG, "Problem while trying to notify user", e); |
9045b1af94e5
revert notifyUser() changes
Carl Byington <carl@five-ten-sg.com>
parents:
417
diff
changeset
|
274 } |
0 | 275 } |
276 | |
277 /** | |
278 * Ask the {@link TerminalBridge} we're connected to to resize to a specific size. | |
279 * @param width | |
280 * @param height | |
281 */ | |
282 public void forceSize(int width, int height) { | |
283 bridge.resizeComputed(width, height, getWidth(), getHeight()); | |
284 } | |
285 | |
286 /** | |
287 * Sets the ability for the TerminalView to display Toast notifications to the user. | |
288 * @param value whether to enable notifications or not | |
289 */ | |
290 public void setNotifications(boolean value) { | |
291 notifications = value; | |
292 } | |
293 | |
294 @Override | |
295 public boolean onCheckIsTextEditor() { | |
296 return true; | |
297 } | |
298 | |
299 @Override | |
300 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { | |
301 outAttrs.imeOptions |= | |
302 EditorInfo.IME_FLAG_NO_EXTRACT_UI | | |
303 EditorInfo.IME_FLAG_NO_ENTER_ACTION | | |
304 EditorInfo.IME_ACTION_NONE; | |
305 outAttrs.inputType = EditorInfo.TYPE_NULL; | |
306 return new BaseInputConnection(this, false) { | |
307 @Override | |
308 public boolean deleteSurroundingText(int leftLength, int rightLength) { | |
309 if (rightLength == 0 && leftLength == 0) { | |
310 return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); | |
311 } | |
312 | |
313 for (int i = 0; i < leftLength; i++) { | |
314 this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); | |
315 } | |
316 | |
317 // TODO: forward delete | |
318 return true; | |
319 } | |
320 }; | |
321 } | |
322 | |
323 public void propagateConsoleText(char[] rawText, int length) { | |
324 if (mAccessibilityActive) { | |
325 synchronized (mAccessibilityLock) { | |
326 mAccessibilityBuffer.append(rawText, 0, length); | |
327 } | |
328 | |
329 if (mAccessibilityInitialized) { | |
330 if (mEventSender != null) { | |
331 removeCallbacks(mEventSender); | |
332 } | |
333 else { | |
334 mEventSender = new AccessibilityEventSender(); | |
335 } | |
336 | |
337 postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); | |
338 } | |
339 } | |
340 } | |
341 | |
342 private class AccessibilityEventSender implements Runnable { | |
343 public void run() { | |
344 synchronized (mAccessibilityLock) { | |
345 if (mCodeMatcher == null) { | |
346 mCodeMatcher = mControlCodes.matcher(mAccessibilityBuffer); | |
347 } | |
348 else { | |
349 mCodeMatcher.reset(mAccessibilityBuffer); | |
350 } | |
351 | |
352 // Strip all control codes out. | |
353 mAccessibilityBuffer = new StringBuffer(mCodeMatcher.replaceAll(" ")); | |
354 // Apply Backspaces using backspace character sequence | |
355 int i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); | |
356 | |
357 while (i != -1) { | |
358 mAccessibilityBuffer = mAccessibilityBuffer.replace(i == 0 ? 0 : i - 1, i | |
359 + BACKSPACE_CODE.length(), ""); | |
360 i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); | |
361 } | |
362 | |
363 if (mAccessibilityBuffer.length() > 0) { | |
364 AccessibilityEvent event = AccessibilityEvent.obtain( | |
365 AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); | |
366 event.setFromIndex(0); | |
367 event.setAddedCount(mAccessibilityBuffer.length()); | |
368 event.getText().add(mAccessibilityBuffer); | |
369 sendAccessibilityEventUnchecked(event); | |
370 mAccessibilityBuffer.setLength(0); | |
371 } | |
372 } | |
373 } | |
374 } | |
375 | |
376 private class AccessibilityStateTester extends AsyncTask<Void, Void, Boolean> { | |
377 @Override | |
378 protected Boolean doInBackground(Void... params) { | |
379 /* | |
380 * Presumably if the accessibility manager is not enabled, we don't | |
381 * need to send accessibility events. | |
382 */ | |
383 final AccessibilityManager accessibility = (AccessibilityManager) context | |
384 .getSystemService(Context.ACCESSIBILITY_SERVICE); | |
385 | |
386 if (!accessibility.isEnabled()) { | |
387 return false; | |
388 } | |
389 | |
390 /* | |
391 * Restrict the set of intents to only accessibility services that | |
392 * have the category FEEDBACK_SPOKEN (aka, screen readers). | |
393 */ | |
394 final Intent screenReaderIntent = new Intent(SCREENREADER_INTENT_ACTION); | |
395 screenReaderIntent.addCategory(SCREENREADER_INTENT_CATEGORY); | |
396 final ContentResolver cr = context.getContentResolver(); | |
397 final List<ResolveInfo> screenReaders = context.getPackageManager().queryIntentServices( | |
398 screenReaderIntent, 0); | |
399 boolean foundScreenReader = false; | |
400 final int N = screenReaders.size(); | |
401 | |
402 for (int i = 0; i < N; i++) { | |
403 final ResolveInfo screenReader = screenReaders.get(i); | |
404 /* | |
405 * All screen readers are expected to implement a content | |
406 * provider that responds to: | |
407 * content://<nameofpackage>.providers.StatusProvider | |
408 */ | |
409 final Cursor cursor = cr.query( | |
410 Uri.parse("content://" + screenReader.serviceInfo.packageName | |
411 + ".providers.StatusProvider"), null, null, null, null); | |
412 | |
413 if (cursor != null && cursor.moveToFirst()) { | |
414 /* | |
415 * These content providers use a special cursor that only has | |
416 * one element, an integer that is 1 if the screen reader is | |
417 * running. | |
418 */ | |
419 final int status = cursor.getInt(0); | |
420 cursor.close(); | |
421 | |
422 if (status == 1) { | |
423 foundScreenReader = true; | |
424 break; | |
425 } | |
426 } | |
427 } | |
428 | |
429 if (foundScreenReader) { | |
430 mControlCodes = Pattern.compile(CONTROL_CODE_PATTERN); | |
431 } | |
432 | |
433 return foundScreenReader; | |
434 } | |
435 | |
436 @Override | |
437 protected void onPostExecute(Boolean result) { | |
438 mAccessibilityActive = result; | |
439 mAccessibilityInitialized = true; | |
440 | |
441 if (result) { | |
442 mEventSender = new AccessibilityEventSender(); | |
443 postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); | |
444 } | |
445 else { | |
446 mAccessibilityBuffer = null; | |
447 } | |
448 } | |
449 } | |
450 | |
451 private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { | |
452 @Override | |
453 public boolean onScale(ScaleGestureDetector detector) { | |
454 float mScaleFactor = detector.getScaleFactor(); | |
455 | |
456 if (mScaleFactor > 1.1) { | |
457 bridge.increaseFontSize(); | |
458 return true; | |
459 } | |
460 else if (mScaleFactor < 0.9) { | |
461 bridge.decreaseFontSize(); | |
462 return true; | |
463 } | |
464 | |
465 return (false); | |
466 } | |
467 } | |
468 | |
469 } |