AccessibleKeyboardViewProxy.java revision e76a9b36cabc3eb9222be245e2cf736169432cd6
15ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette/* 25ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * Copyright (C) 2011 The Android Open Source Project 35ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * 45ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License"); you may not 55ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * use this file except in compliance with the License. You may obtain a copy of 65ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * the License at 75ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * 85ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * http://www.apache.org/licenses/LICENSE-2.0 95ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * 105ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * Unless required by applicable law or agreed to in writing, software 115ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 125ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 135ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * License for the specific language governing permissions and limitations under 145ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * the License. 155ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette */ 165ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 175ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverettepackage com.android.inputmethod.accessibility; 185ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 195ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport android.content.Context; 2058e3f1065ef47e7116299b9d5087ba2a2b6065a2Alan Viveretteimport android.inputmethodservice.InputMethodService; 219a81ce92c381007affe6bb2310bf94c9856eaae1alanvimport android.support.v4.view.AccessibilityDelegateCompat; 229a81ce92c381007affe6bb2310bf94c9856eaae1alanvimport android.support.v4.view.ViewCompat; 239a81ce92c381007affe6bb2310bf94c9856eaae1alanvimport android.support.v4.view.accessibility.AccessibilityEventCompat; 24f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanvimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 255ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport android.view.MotionEvent; 269a81ce92c381007affe6bb2310bf94c9856eaae1alanvimport android.view.View; 275ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 28e7759091ddb5ec18268945d70d9212195bf6497bTadashi G. Takaokaimport com.android.inputmethod.keyboard.Key; 298d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.keyboard.Keyboard; 308d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.keyboard.KeyboardId; 31c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaokaimport com.android.inputmethod.keyboard.MainKeyboardView; 325ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.keyboard.PointerTracker; 338d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.latin.R; 345ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 359a81ce92c381007affe6bb2310bf94c9856eaae1alanvpublic class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { 365ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy(); 375ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 3858e3f1065ef47e7116299b9d5087ba2a2b6065a2Alan Viverette private InputMethodService mInputMethod; 39c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka private MainKeyboardView mView; 409a81ce92c381007affe6bb2310bf94c9856eaae1alanv private AccessibilityEntityProvider mAccessibilityNodeProvider; 415ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 42e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka private Key mLastHoverKey = null; 435ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 446662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv /** 456662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * Inset in pixels to look for keys when the user's finger exits the 46e76a9b36cabc3eb9222be245e2cf736169432cd6alanv * keyboard area. 476662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv */ 486662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv private int mEdgeSlop; 496662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv 502ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka public static void init(InputMethodService inputMethod) { 512ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka sInstance.initInternal(inputMethod); 525ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 535ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 545ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette public static AccessibleKeyboardViewProxy getInstance() { 555ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette return sInstance; 565ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 575ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 585ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette private AccessibleKeyboardViewProxy() { 595ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette // Not publicly instantiable. 605ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 615ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 622ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka private void initInternal(InputMethodService inputMethod) { 6358e3f1065ef47e7116299b9d5087ba2a2b6065a2Alan Viverette mInputMethod = inputMethod; 64e76a9b36cabc3eb9222be245e2cf736169432cd6alanv mEdgeSlop = inputMethod.getResources().getDimensionPixelSize( 65e76a9b36cabc3eb9222be245e2cf736169432cd6alanv R.dimen.accessibility_edge_slop); 665ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 675ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 689a81ce92c381007affe6bb2310bf94c9856eaae1alanv /** 699a81ce92c381007affe6bb2310bf94c9856eaae1alanv * Sets the view wrapped by this proxy. 709a81ce92c381007affe6bb2310bf94c9856eaae1alanv * 719a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param view The view to wrap. 729a81ce92c381007affe6bb2310bf94c9856eaae1alanv */ 73c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka public void setView(MainKeyboardView view) { 749a81ce92c381007affe6bb2310bf94c9856eaae1alanv if (view == null) { 759a81ce92c381007affe6bb2310bf94c9856eaae1alanv // Ignore null views. 769a81ce92c381007affe6bb2310bf94c9856eaae1alanv return; 775ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 785ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 799a81ce92c381007affe6bb2310bf94c9856eaae1alanv mView = view; 805ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 819a81ce92c381007affe6bb2310bf94c9856eaae1alanv // Ensure that the view has an accessibility delegate. 829a81ce92c381007affe6bb2310bf94c9856eaae1alanv ViewCompat.setAccessibilityDelegate(view, this); 8348ccd5528163383a46b597e9d5ea919ddc799f25alanv 8448ccd5528163383a46b597e9d5ea919ddc799f25alanv if (mAccessibilityNodeProvider != null) { 8548ccd5528163383a46b597e9d5ea919ddc799f25alanv mAccessibilityNodeProvider.setView(view); 8648ccd5528163383a46b597e9d5ea919ddc799f25alanv } 879a81ce92c381007affe6bb2310bf94c9856eaae1alanv } 885ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 89f147794fd41491a3383e6aca6d49007f58124068alanv public void setKeyboard(Keyboard keyboard) { 90f147794fd41491a3383e6aca6d49007f58124068alanv if (mAccessibilityNodeProvider != null) { 91f147794fd41491a3383e6aca6d49007f58124068alanv mAccessibilityNodeProvider.setKeyboard(keyboard); 92f147794fd41491a3383e6aca6d49007f58124068alanv } 93f147794fd41491a3383e6aca6d49007f58124068alanv } 94f147794fd41491a3383e6aca6d49007f58124068alanv 959a81ce92c381007affe6bb2310bf94c9856eaae1alanv /** 969a81ce92c381007affe6bb2310bf94c9856eaae1alanv * Proxy method for View.getAccessibilityNodeProvider(). This method is 979a81ce92c381007affe6bb2310bf94c9856eaae1alanv * called in SDK version 15 and higher to obtain the virtual node hierarchy 989a81ce92c381007affe6bb2310bf94c9856eaae1alanv * provider. 999a81ce92c381007affe6bb2310bf94c9856eaae1alanv * 1009a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @return The accessibility node provider for the current keyboard. 1019a81ce92c381007affe6bb2310bf94c9856eaae1alanv */ 1029a81ce92c381007affe6bb2310bf94c9856eaae1alanv @Override 1039a81ce92c381007affe6bb2310bf94c9856eaae1alanv public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) { 104f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv return getAccessibilityNodeProvider(); 1055ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 1065ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 1075ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette /** 108586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * Receives hover events when accessibility is turned on in SDK versions ICS 109586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * and higher. 1105ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * 1115ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * @param event The hover event. 1125ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette * @return {@code true} if the event is handled 1135ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette */ 114586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) { 1155ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette final int x = (int) event.getX(); 1165ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette final int y = (int) event.getY(); 1179a81ce92c381007affe6bb2310bf94c9856eaae1alanv final Key previousKey = mLastHoverKey; 118e76a9b36cabc3eb9222be245e2cf736169432cd6alanv final Key key; 119e76a9b36cabc3eb9222be245e2cf736169432cd6alanv 120e76a9b36cabc3eb9222be245e2cf736169432cd6alanv if (pointInView(x, y)) { 121e76a9b36cabc3eb9222be245e2cf736169432cd6alanv key = tracker.getKeyOn(x, y); 122e76a9b36cabc3eb9222be245e2cf736169432cd6alanv } else { 123e76a9b36cabc3eb9222be245e2cf736169432cd6alanv key = null; 124e76a9b36cabc3eb9222be245e2cf736169432cd6alanv } 1259a81ce92c381007affe6bb2310bf94c9856eaae1alanv 1269a81ce92c381007affe6bb2310bf94c9856eaae1alanv mLastHoverKey = key; 1275ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 1285ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette switch (event.getAction()) { 129c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka case MotionEvent.ACTION_HOVER_EXIT: 1306662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv // Make sure we're not getting an EXIT event because the user slid 1316662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv // off the keyboard area, then force a key press. 132e76a9b36cabc3eb9222be245e2cf736169432cd6alanv if (key != null) { 133f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv getAccessibilityNodeProvider().simulateKeyPress(key); 1346662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv } 1356662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv //$FALL-THROUGH$ 1366662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv case MotionEvent.ACTION_HOVER_ENTER: 1379a81ce92c381007affe6bb2310bf94c9856eaae1alanv return onHoverKey(key, event); 138c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka case MotionEvent.ACTION_HOVER_MOVE: 1399a81ce92c381007affe6bb2310bf94c9856eaae1alanv if (key != previousKey) { 1409a81ce92c381007affe6bb2310bf94c9856eaae1alanv return onTransitionKey(key, previousKey, event); 1419a81ce92c381007affe6bb2310bf94c9856eaae1alanv } else { 1429a81ce92c381007affe6bb2310bf94c9856eaae1alanv return onHoverKey(key, event); 1435ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 1445ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 1455ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 1465ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette return false; 1475ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 1485ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 1499a81ce92c381007affe6bb2310bf94c9856eaae1alanv /** 150f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv * @return A lazily-instantiated node provider for this view proxy. 151f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv */ 152f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv private AccessibilityEntityProvider getAccessibilityNodeProvider() { 153f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv // Instantiate the provide only when requested. Since the system 154f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv // will call this method multiple times it is a good practice to 155f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv // cache the provider instance. 156f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv if (mAccessibilityNodeProvider == null) { 157f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod); 158f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv } 159f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv return mAccessibilityNodeProvider; 160f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv } 161f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv 162f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv /** 1636662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * Utility method to determine whether the given point, in local 1646662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * coordinates, is inside the view, where the area of the view is contracted 1656662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * by the edge slop factor. 1666662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * 1676662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * @param localX The local x-coordinate. 1686662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv * @param localY The local y-coordinate. 1696662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv */ 1706662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv private boolean pointInView(int localX, int localY) { 1716662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv return (localX >= mEdgeSlop) && (localY >= mEdgeSlop) 1726662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv && (localX < (mView.getWidth() - mEdgeSlop)) 1736662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv && (localY < (mView.getHeight() - mEdgeSlop)); 1746662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv } 1756662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv 1766662e2a40dc764d5b6a55c0e30ce650fd834afb6alanv /** 1779a81ce92c381007affe6bb2310bf94c9856eaae1alanv * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT 1789a81ce92c381007affe6bb2310bf94c9856eaae1alanv * on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE 1799a81ce92c381007affe6bb2310bf94c9856eaae1alanv * on the current key. 1809a81ce92c381007affe6bb2310bf94c9856eaae1alanv * 1819a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param currentKey The currently hovered key. 1829a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param previousKey The previously hovered key. 1839a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param event The event that triggered the transition. 1849a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @return {@code true} if the event was handled. 1859a81ce92c381007affe6bb2310bf94c9856eaae1alanv */ 1869a81ce92c381007affe6bb2310bf94c9856eaae1alanv private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) { 1879a81ce92c381007affe6bb2310bf94c9856eaae1alanv final int savedAction = event.getAction(); 1889a81ce92c381007affe6bb2310bf94c9856eaae1alanv 189c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka event.setAction(MotionEvent.ACTION_HOVER_EXIT); 1909a81ce92c381007affe6bb2310bf94c9856eaae1alanv onHoverKey(previousKey, event); 1919a81ce92c381007affe6bb2310bf94c9856eaae1alanv 192c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka event.setAction(MotionEvent.ACTION_HOVER_ENTER); 1939a81ce92c381007affe6bb2310bf94c9856eaae1alanv onHoverKey(currentKey, event); 1949a81ce92c381007affe6bb2310bf94c9856eaae1alanv 195c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka event.setAction(MotionEvent.ACTION_HOVER_MOVE); 1969a81ce92c381007affe6bb2310bf94c9856eaae1alanv final boolean handled = onHoverKey(currentKey, event); 1979a81ce92c381007affe6bb2310bf94c9856eaae1alanv 1989a81ce92c381007affe6bb2310bf94c9856eaae1alanv event.setAction(savedAction); 1999a81ce92c381007affe6bb2310bf94c9856eaae1alanv 2009a81ce92c381007affe6bb2310bf94c9856eaae1alanv return handled; 2019a81ce92c381007affe6bb2310bf94c9856eaae1alanv } 2029a81ce92c381007affe6bb2310bf94c9856eaae1alanv 2039a81ce92c381007affe6bb2310bf94c9856eaae1alanv /** 2049a81ce92c381007affe6bb2310bf94c9856eaae1alanv * Handles a hover event on a key. If {@link Key} extended View, this would 2059a81ce92c381007affe6bb2310bf94c9856eaae1alanv * be analogous to calling View.onHoverEvent(MotionEvent). 2069a81ce92c381007affe6bb2310bf94c9856eaae1alanv * 2079a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param key The currently hovered key. 2089a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @param event The hover event. 2099a81ce92c381007affe6bb2310bf94c9856eaae1alanv * @return {@code true} if the event was handled. 2109a81ce92c381007affe6bb2310bf94c9856eaae1alanv */ 2119a81ce92c381007affe6bb2310bf94c9856eaae1alanv private boolean onHoverKey(Key key, MotionEvent event) { 2129a81ce92c381007affe6bb2310bf94c9856eaae1alanv // Null keys can't receive events. 2139a81ce92c381007affe6bb2310bf94c9856eaae1alanv if (key == null) { 2149a81ce92c381007affe6bb2310bf94c9856eaae1alanv return false; 2155ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 2165ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 217f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv final AccessibilityEntityProvider provider = getAccessibilityNodeProvider(); 218f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv 2199a81ce92c381007affe6bb2310bf94c9856eaae1alanv switch (event.getAction()) { 220c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka case MotionEvent.ACTION_HOVER_ENTER: 221f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv provider.sendAccessibilityEventForKey( 222f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER); 223f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv provider.performActionForKey( 224f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null); 2259a81ce92c381007affe6bb2310bf94c9856eaae1alanv break; 226c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka case MotionEvent.ACTION_HOVER_EXIT: 227f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv provider.sendAccessibilityEventForKey( 228f2eba97cc09c86f9a84b61cccf3f233e1fb85a6calanv key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT); 2299a81ce92c381007affe6bb2310bf94c9856eaae1alanv break; 2305ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette } 2315ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 2329a81ce92c381007affe6bb2310bf94c9856eaae1alanv return true; 2339a81ce92c381007affe6bb2310bf94c9856eaae1alanv } 2345ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 2359a81ce92c381007affe6bb2310bf94c9856eaae1alanv /** 2368d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv * Notifies the user of changes in the keyboard shift state. 2378d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv */ 2388d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv public void notifyShiftState() { 2398d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final Keyboard keyboard = mView.getKeyboard(); 2408d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final KeyboardId keyboardId = keyboard.mId; 2418d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final int elementId = keyboardId.mElementId; 2428d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final Context context = mView.getContext(); 2438d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final CharSequence text; 2448d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2458d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv switch (elementId) { 2468d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: 2478d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: 2488d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv text = context.getText(R.string.spoken_description_shiftmode_locked); 2498d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2508d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: 2518d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: 2528d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: 2538d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv text = context.getText(R.string.spoken_description_shiftmode_on); 2548d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2558d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv default: 2568d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv text = context.getText(R.string.spoken_description_shiftmode_off); 2578d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2588d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2595f312c9c1546da9f73d02f911d3365da4ff658fbalanv AccessibilityUtils.getInstance().announceForAccessibility(mView, text); 2608d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2618d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2628d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv /** 2638d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv * Notifies the user of changes in the keyboard symbols state. 2648d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv */ 2658d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv public void notifySymbolsState() { 2668d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final Keyboard keyboard = mView.getKeyboard(); 2678d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final Context context = mView.getContext(); 2688d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final KeyboardId keyboardId = keyboard.mId; 2698d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final int elementId = keyboardId.mElementId; 2708d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final int resId; 2718d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2728d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv switch (elementId) { 2738d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET: 2748d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: 2758d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: 2768d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: 2778d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: 2788d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv resId = R.string.spoken_description_mode_alpha; 2798d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2808d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_SYMBOLS: 2818d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: 2828d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv resId = R.string.spoken_description_mode_symbol; 2838d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2848d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_PHONE: 2858d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv resId = R.string.spoken_description_mode_phone; 2868d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2878d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case KeyboardId.ELEMENT_PHONE_SYMBOLS: 2888d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv resId = R.string.spoken_description_mode_phone_shift; 2898d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 2908d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv default: 2918d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv resId = -1; 2928d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2938d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2948d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv if (resId < 0) { 2958d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv return; 2968d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2978d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 2988d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv final String text = context.getString(resId); 2995f312c9c1546da9f73d02f911d3365da4ff658fbalanv AccessibilityUtils.getInstance().announceForAccessibility(mView, text); 3008d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 3015ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette} 302